Skip to content

syntax: use lookahead to distinguish inner and outer attributes, instead of passing the latter around. #23331

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 17, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 4 additions & 8 deletions src/libsyntax/ext/quote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,8 +361,7 @@ pub mod rt {
parse::parse_stmt_from_source_str("<quote expansion>".to_string(),
s,
self.cfg(),
Vec::new(),
self.parse_sess())
self.parse_sess()).expect("parse error")
}

fn parse_expr(&self, s: String) -> P<ast::Expr> {
Expand Down Expand Up @@ -407,16 +406,15 @@ pub fn expand_quote_expr<'cx>(cx: &'cx mut ExtCtxt,
sp: Span,
tts: &[ast::TokenTree])
-> Box<base::MacResult+'cx> {
let expanded = expand_parse_call(cx, sp, "parse_expr", Vec::new(), tts);
let expanded = expand_parse_call(cx, sp, "parse_expr", vec!(), tts);
base::MacEager::expr(expanded)
}

pub fn expand_quote_item<'cx>(cx: &mut ExtCtxt,
sp: Span,
tts: &[ast::TokenTree])
-> Box<base::MacResult+'cx> {
let expanded = expand_parse_call(cx, sp, "parse_item_with_outer_attributes",
vec!(), tts);
let expanded = expand_parse_call(cx, sp, "parse_item", vec!(), tts);
base::MacEager::expr(expanded)
}

Expand Down Expand Up @@ -448,9 +446,7 @@ pub fn expand_quote_stmt(cx: &mut ExtCtxt,
sp: Span,
tts: &[ast::TokenTree])
-> Box<base::MacResult+'static> {
let e_attrs = cx.expr_vec_ng(sp);
let expanded = expand_parse_call(cx, sp, "parse_stmt",
vec!(e_attrs), tts);
let expanded = expand_parse_call(cx, sp, "parse_stmt", vec!(), tts);
base::MacEager::expr(expanded)
}

Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax/ext/source_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree
-> Option<SmallVector<P<ast::Item>>> {
let mut ret = SmallVector::zero();
while self.p.token != token::Eof {
match self.p.parse_item_with_outer_attributes() {
match self.p.parse_item() {
Some(item) => ret.push(item),
None => self.p.span_fatal(
self.p.span,
Expand Down
7 changes: 5 additions & 2 deletions src/libsyntax/ext/tt/macro_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -521,12 +521,15 @@ pub fn parse_nt(p: &mut Parser, sp: Span, name: &str) -> Nonterminal {
// check at the beginning and the parser checks after each bump
p.check_unknown_macro_variable();
match name {
"item" => match p.parse_item(Vec::new()) {
"item" => match p.parse_item() {
Some(i) => token::NtItem(i),
None => p.fatal("expected an item keyword")
},
"block" => token::NtBlock(p.parse_block()),
"stmt" => token::NtStmt(p.parse_stmt(Vec::new())),
"stmt" => match p.parse_stmt() {
Some(s) => token::NtStmt(s),
None => p.fatal("expected a statement")
},
"pat" => token::NtPat(p.parse_pat()),
"expr" => token::NtExpr(p.parse_expr()),
"ty" => token::NtTy(p.parse_ty()),
Expand Down
19 changes: 5 additions & 14 deletions src/libsyntax/ext/tt/macro_rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal};
use ext::tt::macro_parser::{parse, parse_or_else};
use parse::lexer::new_tt_reader;
use parse::parser::Parser;
use parse::attr::ParserAttr;
use parse::token::{self, special_idents, gensym_ident, NtTT, Token};
use parse::token::Token::*;
use print;
Expand Down Expand Up @@ -68,15 +67,8 @@ impl<'a> MacResult for ParserAnyMacro<'a> {
}
fn make_items(self: Box<ParserAnyMacro<'a>>) -> Option<SmallVector<P<ast::Item>>> {
let mut ret = SmallVector::zero();
loop {
let mut parser = self.parser.borrow_mut();
// so... do outer attributes attached to the macro invocation
// just disappear? This question applies to make_impl_items, as
// well.
match parser.parse_item_with_outer_attributes() {
Some(item) => ret.push(item),
None => break
}
while let Some(item) = self.parser.borrow_mut().parse_item() {
ret.push(item);
}
self.ensure_complete_parse(false);
Some(ret)
Expand All @@ -89,18 +81,17 @@ impl<'a> MacResult for ParserAnyMacro<'a> {
let mut parser = self.parser.borrow_mut();
match parser.token {
token::Eof => break,
_ => ret.push(parser.parse_impl_item_with_outer_attributes())
_ => ret.push(parser.parse_impl_item())
}
}
self.ensure_complete_parse(false);
Some(ret)
}

fn make_stmt(self: Box<ParserAnyMacro<'a>>) -> Option<P<ast::Stmt>> {
let attrs = self.parser.borrow_mut().parse_outer_attributes();
let ret = self.parser.borrow_mut().parse_stmt(attrs);
let ret = self.parser.borrow_mut().parse_stmt();
self.ensure_complete_parse(true);
Some(ret)
ret
}
}

Expand Down
58 changes: 26 additions & 32 deletions src/libsyntax/parse/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@ use ptr::P;
/// A parser that can parse attributes.
pub trait ParserAttr {
fn parse_outer_attributes(&mut self) -> Vec<ast::Attribute>;
fn parse_inner_attributes(&mut self) -> Vec<ast::Attribute>;
fn parse_attribute(&mut self, permit_inner: bool) -> ast::Attribute;
fn parse_inner_attrs_and_next(&mut self)
-> (Vec<ast::Attribute>, Vec<ast::Attribute>);
fn parse_meta_item(&mut self) -> P<ast::MetaItem>;
fn parse_meta_seq(&mut self) -> Vec<P<ast::MetaItem>>;
fn parse_optional_meta(&mut self) -> Vec<P<ast::MetaItem>>;
Expand Down Expand Up @@ -118,45 +117,40 @@ impl<'a> ParserAttr for Parser<'a> {

/// Parse attributes that appear after the opening of an item. These should
/// be preceded by an exclamation mark, but we accept and warn about one
/// terminated by a semicolon. In addition to a vector of inner attributes,
/// this function also returns a vector that may contain the first outer
/// attribute of the next item (since we can't know whether the attribute
/// is an inner attribute of the containing item or an outer attribute of
/// the first contained item until we see the semi).

/// matches inner_attrs* outer_attr?
/// you can make the 'next' field an Option, but the result is going to be
/// more useful as a vector.
fn parse_inner_attrs_and_next(&mut self)
-> (Vec<ast::Attribute> , Vec<ast::Attribute> ) {
let mut inner_attrs: Vec<ast::Attribute> = Vec::new();
let mut next_outer_attrs: Vec<ast::Attribute> = Vec::new();
/// terminated by a semicolon.

/// matches inner_attrs*
fn parse_inner_attributes(&mut self) -> Vec<ast::Attribute> {
let mut attrs: Vec<ast::Attribute> = vec![];
loop {
let attr = match self.token {
match self.token {
token::Pound => {
self.parse_attribute(true)
// Don't even try to parse if it's not an inner attribute.
if !self.look_ahead(1, |t| t == &token::Not) {
break;
}

let attr = self.parse_attribute(true);
assert!(attr.node.style == ast::AttrInner);
attrs.push(attr);
}
token::DocComment(s) => {
// we need to get the position of this token before we bump.
let Span { lo, hi, .. } = self.span;
self.bump();
attr::mk_sugared_doc_attr(attr::mk_attr_id(),
self.id_to_interned_str(s.ident()),
lo,
hi)
}
_ => {
break;
let attr = attr::mk_sugared_doc_attr(attr::mk_attr_id(),
self.id_to_interned_str(s.ident()),
lo, hi);
if attr.node.style == ast::AttrInner {
attrs.push(attr);
self.bump();
} else {
break;
}
}
};
if attr.node.style == ast::AttrInner {
inner_attrs.push(attr);
} else {
next_outer_attrs.push(attr);
break;
_ => break
}
}
(inner_attrs, next_outer_attrs)
attrs
}

/// matches meta_item = IDENT
Expand Down
14 changes: 5 additions & 9 deletions src/libsyntax/parse/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,7 @@ pub fn parse_crate_attrs_from_file(
cfg: ast::CrateConfig,
sess: &ParseSess
) -> Vec<ast::Attribute> {
let mut parser = new_parser_from_file(sess, cfg, input);
let (inner, _) = parser.parse_inner_attrs_and_next();
inner
new_parser_from_file(sess, cfg, input).parse_inner_attributes()
}

pub fn parse_crate_from_source_str(name: String,
Expand All @@ -122,8 +120,7 @@ pub fn parse_crate_attrs_from_source_str(name: String,
cfg,
name,
source);
let (inner, _) = maybe_aborted(p.parse_inner_attrs_and_next(),p);
inner
maybe_aborted(p.parse_inner_attributes(), p)
}

pub fn parse_expr_from_source_str(name: String,
Expand All @@ -141,7 +138,7 @@ pub fn parse_item_from_source_str(name: String,
sess: &ParseSess)
-> Option<P<ast::Item>> {
let mut p = new_parser_from_source_str(sess, cfg, name, source);
maybe_aborted(p.parse_item_with_outer_attributes(),p)
maybe_aborted(p.parse_item(),p)
}

pub fn parse_meta_from_source_str(name: String,
Expand All @@ -156,16 +153,15 @@ pub fn parse_meta_from_source_str(name: String,
pub fn parse_stmt_from_source_str(name: String,
source: String,
cfg: ast::CrateConfig,
attrs: Vec<ast::Attribute> ,
sess: &ParseSess)
-> P<ast::Stmt> {
-> Option<P<ast::Stmt>> {
let mut p = new_parser_from_source_str(
sess,
cfg,
name,
source
);
maybe_aborted(p.parse_stmt(attrs),p)
maybe_aborted(p.parse_stmt(), p)
}

// Note: keep in sync with `with_hygiene::parse_tts_from_source_str`
Expand Down
Loading