syntax: use lookahead to distinguish inner and outer attributes, instead of passing the latter around.
This commit is contained in:
parent
79dd393a4f
commit
9889aae13e
11 changed files with 325 additions and 512 deletions
|
@ -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> {
|
||||
|
@ -407,7 +406,7 @@ 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)
|
||||
}
|
||||
|
||||
|
@ -415,8 +414,7 @@ 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)
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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()),
|
||||
|
|
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -89,7 +81,7 @@ 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);
|
||||
|
@ -97,10 +89,9 @@ impl<'a> MacResult for ParserAnyMacro<'a> {
|
|||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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>>;
|
||||
|
@ -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).
|
||||
/// terminated by a semicolon.
|
||||
|
||||
/// 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();
|
||||
/// 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(),
|
||||
let attr = attr::mk_sugared_doc_attr(attr::mk_attr_id(),
|
||||
self.id_to_interned_str(s.ident()),
|
||||
lo,
|
||||
hi)
|
||||
}
|
||||
_ => {
|
||||
break;
|
||||
}
|
||||
};
|
||||
lo, hi);
|
||||
if attr.node.style == ast::AttrInner {
|
||||
inner_attrs.push(attr);
|
||||
attrs.push(attr);
|
||||
self.bump();
|
||||
} else {
|
||||
next_outer_attrs.push(attr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
(inner_attrs, next_outer_attrs)
|
||||
_ => break
|
||||
}
|
||||
}
|
||||
attrs
|
||||
}
|
||||
|
||||
/// matches meta_item = IDENT
|
||||
|
|
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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`
|
||||
|
|
|
@ -39,7 +39,7 @@ use ast::{LitStr, LitInt, Local, LocalLet};
|
|||
use ast::{MacStmtWithBraces, MacStmtWithSemicolon, MacStmtWithoutBraces};
|
||||
use ast::{MutImmutable, MutMutable, Mac_, MacInvocTT, MatchSource};
|
||||
use ast::{MutTy, BiMul, Mutability};
|
||||
use ast::{MethodImplItem, NamedField, UnNeg, NoReturn, NodeId, UnNot};
|
||||
use ast::{MethodImplItem, NamedField, UnNeg, NoReturn, UnNot};
|
||||
use ast::{Pat, PatEnum, PatIdent, PatLit, PatRange, PatRegion, PatStruct};
|
||||
use ast::{PatTup, PatBox, PatWild, PatWildMulti, PatWildSingle};
|
||||
use ast::{PolyTraitRef, QSelf};
|
||||
|
@ -117,11 +117,6 @@ pub enum BoundParsingMode {
|
|||
Modified,
|
||||
}
|
||||
|
||||
/// The `Err` case indicates a failure to parse any kind of item.
|
||||
/// The attributes are returned.
|
||||
type MaybeItem = Result<P<Item>, Vec<Attribute>>;
|
||||
|
||||
|
||||
/// Possibly accept an `token::Interpolated` expression (a pre-parsed expression
|
||||
/// dropped into the token stream, which happens while parsing the result of
|
||||
/// macro expansion). Placement of these is not as complex as I feared it would
|
||||
|
@ -208,7 +203,7 @@ macro_rules! maybe_whole {
|
|||
}
|
||||
}
|
||||
);
|
||||
(Some $p:expr, $constructor:ident) => (
|
||||
(Some deref $p:expr, $constructor:ident) => (
|
||||
{
|
||||
let found = match ($p).token {
|
||||
token::Interpolated(token::$constructor(_)) => {
|
||||
|
@ -217,7 +212,7 @@ macro_rules! maybe_whole {
|
|||
_ => None
|
||||
};
|
||||
if let Some(token::Interpolated(token::$constructor(x))) = found {
|
||||
return Some(x.clone());
|
||||
return Some((*x).clone());
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -1240,41 +1235,6 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Parses `type Foo;` in a trait declaration only. The `type` keyword has
|
||||
/// already been parsed.
|
||||
fn parse_assoc_ty_in_trait(&mut self, attrs: Vec<Attribute>)
|
||||
-> P<TraitItem> {
|
||||
let TyParam {id, ident, bounds, default, span} = self.parse_ty_param();
|
||||
self.expect(&token::Semi);
|
||||
P(TraitItem {
|
||||
id: id,
|
||||
ident: ident,
|
||||
attrs: attrs,
|
||||
node: TypeTraitItem(bounds, default),
|
||||
span: span,
|
||||
})
|
||||
}
|
||||
|
||||
/// Parses `type Foo = TYPE;` in an implementation declaration only. The
|
||||
/// `type` keyword has already been parsed.
|
||||
fn parse_assoc_ty_in_impl(&mut self, attrs: Vec<Attribute>, vis: Visibility)
|
||||
-> P<ImplItem> {
|
||||
let lo = self.span.lo;
|
||||
let ident = self.parse_ident();
|
||||
self.expect(&token::Eq);
|
||||
let typ = self.parse_ty_sum();
|
||||
let hi = self.span.hi;
|
||||
self.expect(&token::Semi);
|
||||
P(ImplItem {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: mk_sp(lo, hi),
|
||||
ident: ident,
|
||||
vis: vis,
|
||||
attrs: attrs,
|
||||
node: TypeImplItem(typ),
|
||||
})
|
||||
}
|
||||
|
||||
/// Parse the items in a trait declaration
|
||||
pub fn parse_trait_items(&mut self) -> Vec<P<TraitItem>> {
|
||||
self.parse_unspanned_seq(
|
||||
|
@ -1282,13 +1242,14 @@ impl<'a> Parser<'a> {
|
|||
&token::CloseDelim(token::Brace),
|
||||
seq_sep_none(),
|
||||
|p| {
|
||||
let lo = p.span.lo;
|
||||
let mut attrs = p.parse_outer_attributes();
|
||||
|
||||
if p.eat_keyword(keywords::Type) {
|
||||
p.parse_assoc_ty_in_trait(attrs)
|
||||
let (name, node) = if p.eat_keyword(keywords::Type) {
|
||||
let TyParam {ident, bounds, default, ..} = p.parse_ty_param();
|
||||
p.expect(&token::Semi);
|
||||
(ident, TypeTraitItem(bounds, default))
|
||||
} else {
|
||||
let lo = p.span.lo;
|
||||
|
||||
let style = p.parse_unsafety();
|
||||
let abi = if p.eat_keyword(keywords::Extern) {
|
||||
p.parse_opt_abi().unwrap_or(abi::C)
|
||||
|
@ -1316,7 +1277,6 @@ impl<'a> Parser<'a> {
|
|||
explicit_self: explicit_self,
|
||||
};
|
||||
|
||||
let hi = p.last_span.hi;
|
||||
let body = match p.token {
|
||||
token::Semi => {
|
||||
p.bump();
|
||||
|
@ -1337,15 +1297,16 @@ impl<'a> Parser<'a> {
|
|||
token_str)[..])
|
||||
}
|
||||
};
|
||||
(ident, ast::MethodTraitItem(sig, body))
|
||||
};
|
||||
|
||||
P(TraitItem {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
ident: ident,
|
||||
ident: name,
|
||||
attrs: attrs,
|
||||
node: ast::MethodTraitItem(sig, body),
|
||||
span: mk_sp(lo, hi),
|
||||
node: node,
|
||||
span: mk_sp(lo, p.last_span.hi),
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -3647,41 +3608,47 @@ impl<'a> Parser<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
/// Get an expected item after attributes error message.
|
||||
fn expected_item_err(attrs: &[Attribute]) -> &'static str {
|
||||
match attrs.last() {
|
||||
/// Emit an expected item after attributes error.
|
||||
fn expected_item_err(&self, attrs: &[Attribute]) {
|
||||
let message = match attrs.last() {
|
||||
Some(&Attribute { node: ast::Attribute_ { is_sugared_doc: true, .. }, .. }) => {
|
||||
"expected item after doc comment"
|
||||
}
|
||||
_ => "expected item after attributes",
|
||||
}
|
||||
};
|
||||
|
||||
self.span_err(self.last_span, message);
|
||||
}
|
||||
|
||||
/// Parse a statement. may include decl.
|
||||
/// Precondition: any attributes are parsed already
|
||||
pub fn parse_stmt(&mut self, item_attrs: Vec<Attribute>) -> P<Stmt> {
|
||||
maybe_whole!(self, NtStmt);
|
||||
pub fn parse_stmt(&mut self) -> Option<P<Stmt>> {
|
||||
self.parse_stmt_().map(P)
|
||||
}
|
||||
|
||||
fn parse_stmt_(&mut self) -> Option<Stmt> {
|
||||
maybe_whole!(Some deref self, NtStmt);
|
||||
|
||||
fn check_expected_item(p: &mut Parser, attrs: &[Attribute]) {
|
||||
// If we have attributes then we should have an item
|
||||
if !attrs.is_empty() {
|
||||
let last_span = p.last_span;
|
||||
p.span_err(last_span, Parser::expected_item_err(attrs));
|
||||
p.expected_item_err(attrs);
|
||||
}
|
||||
}
|
||||
|
||||
let lo = self.span.lo;
|
||||
if self.check_keyword(keywords::Let) {
|
||||
check_expected_item(self, &item_attrs[..]);
|
||||
let attrs = self.parse_outer_attributes();
|
||||
|
||||
Some(if self.check_keyword(keywords::Let) {
|
||||
check_expected_item(self, &attrs);
|
||||
self.expect_keyword(keywords::Let);
|
||||
let decl = self.parse_let();
|
||||
P(spanned(lo, decl.span.hi, StmtDecl(decl, ast::DUMMY_NODE_ID)))
|
||||
spanned(lo, decl.span.hi, StmtDecl(decl, ast::DUMMY_NODE_ID))
|
||||
} else if self.token.is_ident()
|
||||
&& !self.token.is_any_keyword()
|
||||
&& self.look_ahead(1, |t| *t == token::Not) {
|
||||
// it's a macro invocation:
|
||||
|
||||
check_expected_item(self, &item_attrs[..]);
|
||||
check_expected_item(self, &attrs);
|
||||
|
||||
// Potential trouble: if we allow macros with paths instead of
|
||||
// idents, we'd need to look ahead past the whole path here...
|
||||
|
@ -3728,12 +3695,11 @@ impl<'a> Parser<'a> {
|
|||
};
|
||||
|
||||
if id.name == token::special_idents::invalid.name {
|
||||
P(spanned(lo,
|
||||
hi,
|
||||
spanned(lo, hi,
|
||||
StmtMac(P(spanned(lo,
|
||||
hi,
|
||||
MacInvocTT(pth, tts, EMPTY_CTXT))),
|
||||
style)))
|
||||
style))
|
||||
} else {
|
||||
// if it has a special ident, it's definitely an item
|
||||
//
|
||||
|
@ -3747,35 +3713,38 @@ impl<'a> Parser<'a> {
|
|||
followed by a semicolon");
|
||||
}
|
||||
}
|
||||
P(spanned(lo, hi, StmtDecl(
|
||||
spanned(lo, hi, StmtDecl(
|
||||
P(spanned(lo, hi, DeclItem(
|
||||
self.mk_item(
|
||||
lo, hi, id /*id is good here*/,
|
||||
ItemMac(spanned(lo, hi, MacInvocTT(pth, tts, EMPTY_CTXT))),
|
||||
Inherited, Vec::new(/*no attrs*/))))),
|
||||
ast::DUMMY_NODE_ID)))
|
||||
ast::DUMMY_NODE_ID))
|
||||
}
|
||||
} else {
|
||||
let found_attrs = !item_attrs.is_empty();
|
||||
let item_err = Parser::expected_item_err(&item_attrs[..]);
|
||||
match self.parse_item_(item_attrs, false) {
|
||||
Ok(i) => {
|
||||
match self.parse_item_(attrs, false) {
|
||||
Some(i) => {
|
||||
let hi = i.span.hi;
|
||||
let decl = P(spanned(lo, hi, DeclItem(i)));
|
||||
P(spanned(lo, hi, StmtDecl(decl, ast::DUMMY_NODE_ID)))
|
||||
spanned(lo, hi, StmtDecl(decl, ast::DUMMY_NODE_ID))
|
||||
}
|
||||
Err(_) => {
|
||||
if found_attrs {
|
||||
let last_span = self.last_span;
|
||||
self.span_err(last_span, item_err);
|
||||
None => {
|
||||
// Do not attempt to parse an expression if we're done here.
|
||||
if self.token == token::Semi {
|
||||
self.bump();
|
||||
return None;
|
||||
}
|
||||
|
||||
if self.token == token::CloseDelim(token::Brace) {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Remainder are line-expr stmts.
|
||||
let e = self.parse_expr_res(RESTRICTION_STMT_EXPR);
|
||||
P(spanned(lo, e.span.hi, StmtExpr(e, ast::DUMMY_NODE_ID)))
|
||||
}
|
||||
spanned(lo, e.span.hi, StmtExpr(e, ast::DUMMY_NODE_ID))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Is this expression a successfully-parsed statement?
|
||||
|
@ -3798,61 +3767,35 @@ impl<'a> Parser<'a> {
|
|||
"place this code inside a block");
|
||||
}
|
||||
|
||||
return self.parse_block_tail_(lo, DefaultBlock, Vec::new());
|
||||
self.parse_block_tail(lo, DefaultBlock)
|
||||
}
|
||||
|
||||
/// Parse a block. Inner attrs are allowed.
|
||||
fn parse_inner_attrs_and_block(&mut self)
|
||||
-> (Vec<Attribute> , P<Block>) {
|
||||
|
||||
fn parse_inner_attrs_and_block(&mut self) -> (Vec<Attribute>, P<Block>) {
|
||||
maybe_whole!(pair_empty self, NtBlock);
|
||||
|
||||
let lo = self.span.lo;
|
||||
self.expect(&token::OpenDelim(token::Brace));
|
||||
let (inner, next) = self.parse_inner_attrs_and_next();
|
||||
|
||||
(inner, self.parse_block_tail_(lo, DefaultBlock, next))
|
||||
}
|
||||
|
||||
/// Precondition: already parsed the '{'.
|
||||
fn parse_block_tail(&mut self, lo: BytePos, s: BlockCheckMode) -> P<Block> {
|
||||
self.parse_block_tail_(lo, s, Vec::new())
|
||||
(self.parse_inner_attributes(),
|
||||
self.parse_block_tail(lo, DefaultBlock))
|
||||
}
|
||||
|
||||
/// Parse the rest of a block expression or function body
|
||||
fn parse_block_tail_(&mut self, lo: BytePos, s: BlockCheckMode,
|
||||
first_item_attrs: Vec<Attribute>) -> P<Block> {
|
||||
/// Precondition: already parsed the '{'.
|
||||
fn parse_block_tail(&mut self, lo: BytePos, s: BlockCheckMode) -> P<Block> {
|
||||
let mut stmts = vec![];
|
||||
let mut expr = None;
|
||||
let mut attributes_box = first_item_attrs;
|
||||
|
||||
while self.token != token::CloseDelim(token::Brace) {
|
||||
// parsing items even when they're not allowed lets us give
|
||||
// better error messages and recover more gracefully.
|
||||
attributes_box.push_all(&self.parse_outer_attributes());
|
||||
match self.token {
|
||||
token::Semi => {
|
||||
if !attributes_box.is_empty() {
|
||||
let last_span = self.last_span;
|
||||
self.span_err(last_span,
|
||||
Parser::expected_item_err(&attributes_box[..]));
|
||||
attributes_box = Vec::new();
|
||||
}
|
||||
self.bump(); // empty
|
||||
}
|
||||
token::CloseDelim(token::Brace) => {
|
||||
// fall through and out.
|
||||
}
|
||||
_ => {
|
||||
let stmt = self.parse_stmt(attributes_box);
|
||||
attributes_box = Vec::new();
|
||||
stmt.and_then(|Spanned {node, span}| match node {
|
||||
StmtExpr(e, stmt_id) => {
|
||||
self.handle_expression_like_statement(e,
|
||||
stmt_id,
|
||||
span,
|
||||
&mut stmts,
|
||||
&mut expr);
|
||||
while !self.eat(&token::CloseDelim(token::Brace)) {
|
||||
let Spanned {node, span} = if let Some(s) = self.parse_stmt_() {
|
||||
s
|
||||
} else {
|
||||
// Found only `;` or `}`.
|
||||
continue;
|
||||
};
|
||||
match node {
|
||||
StmtExpr(e, _) => {
|
||||
self.handle_expression_like_statement(e, span, &mut stmts, &mut expr);
|
||||
}
|
||||
StmtMac(mac, MacStmtWithoutBraces) => {
|
||||
// statement macro without braces; might be an
|
||||
|
@ -3860,22 +3803,19 @@ impl<'a> Parser<'a> {
|
|||
match self.token {
|
||||
token::Semi => {
|
||||
stmts.push(P(Spanned {
|
||||
node: StmtMac(mac,
|
||||
MacStmtWithSemicolon),
|
||||
node: StmtMac(mac, MacStmtWithSemicolon),
|
||||
span: span,
|
||||
}));
|
||||
self.bump();
|
||||
}
|
||||
_ => {
|
||||
let e = self.mk_mac_expr(span.lo,
|
||||
span.hi,
|
||||
let e = self.mk_mac_expr(span.lo, span.hi,
|
||||
mac.and_then(|m| m.node));
|
||||
let e = self.parse_dot_or_call_expr_with(e);
|
||||
let e = self.parse_more_binops(e, 0);
|
||||
let e = self.parse_assign_expr_with(e);
|
||||
self.handle_expression_like_statement(
|
||||
e,
|
||||
ast::DUMMY_NODE_ID,
|
||||
span,
|
||||
&mut stmts,
|
||||
&mut expr);
|
||||
|
@ -3887,8 +3827,7 @@ impl<'a> Parser<'a> {
|
|||
match self.token {
|
||||
token::Semi => {
|
||||
stmts.push(P(Spanned {
|
||||
node: StmtMac(m,
|
||||
MacStmtWithSemicolon),
|
||||
node: StmtMac(m, MacStmtWithSemicolon),
|
||||
span: span,
|
||||
}));
|
||||
self.bump();
|
||||
|
@ -3896,9 +3835,7 @@ impl<'a> Parser<'a> {
|
|||
token::CloseDelim(token::Brace) => {
|
||||
// if a block ends in `m!(arg)` without
|
||||
// a `;`, it must be an expr
|
||||
expr = Some(
|
||||
self.mk_mac_expr(span.lo,
|
||||
span.hi,
|
||||
expr = Some(self.mk_mac_expr(span.lo, span.hi,
|
||||
m.and_then(|x| x.node)));
|
||||
}
|
||||
_ => {
|
||||
|
@ -3919,32 +3856,21 @@ impl<'a> Parser<'a> {
|
|||
span: span
|
||||
}));
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !attributes_box.is_empty() {
|
||||
let last_span = self.last_span;
|
||||
self.span_err(last_span,
|
||||
Parser::expected_item_err(&attributes_box[..]));
|
||||
}
|
||||
|
||||
let hi = self.span.hi;
|
||||
self.bump();
|
||||
P(ast::Block {
|
||||
stmts: stmts,
|
||||
expr: expr,
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
rules: s,
|
||||
span: mk_sp(lo, hi),
|
||||
span: mk_sp(lo, self.last_span.hi),
|
||||
})
|
||||
}
|
||||
|
||||
fn handle_expression_like_statement(
|
||||
&mut self,
|
||||
e: P<Expr>,
|
||||
stmt_id: NodeId,
|
||||
span: Span,
|
||||
stmts: &mut Vec<P<Stmt>>,
|
||||
last_block_expr: &mut Option<P<Expr>>) {
|
||||
|
@ -3964,14 +3890,14 @@ impl<'a> Parser<'a> {
|
|||
expn_id: span.expn_id,
|
||||
};
|
||||
stmts.push(P(Spanned {
|
||||
node: StmtSemi(e, stmt_id),
|
||||
node: StmtSemi(e, ast::DUMMY_NODE_ID),
|
||||
span: span_with_semi,
|
||||
}));
|
||||
}
|
||||
token::CloseDelim(token::Brace) => *last_block_expr = Some(e),
|
||||
_ => {
|
||||
stmts.push(P(Spanned {
|
||||
node: StmtExpr(e, stmt_id),
|
||||
node: StmtExpr(e, ast::DUMMY_NODE_ID),
|
||||
span: span
|
||||
}));
|
||||
}
|
||||
|
@ -4626,14 +4552,30 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
/// Parse an impl item.
|
||||
pub fn parse_impl_item_with_outer_attributes(&mut self) -> P<ImplItem> {
|
||||
let attrs = self.parse_outer_attributes();
|
||||
pub fn parse_impl_item(&mut self) -> P<ImplItem> {
|
||||
let lo = self.span.lo;
|
||||
let mut attrs = self.parse_outer_attributes();
|
||||
let vis = self.parse_visibility();
|
||||
if self.eat_keyword(keywords::Type) {
|
||||
self.parse_assoc_ty_in_impl(attrs, vis)
|
||||
let (name, node) = if self.eat_keyword(keywords::Type) {
|
||||
let name = self.parse_ident();
|
||||
self.expect(&token::Eq);
|
||||
let typ = self.parse_ty_sum();
|
||||
self.expect(&token::Semi);
|
||||
(name, TypeImplItem(typ))
|
||||
} else {
|
||||
self.parse_method(attrs, vis)
|
||||
}
|
||||
let (name, inner_attrs, node) = self.parse_impl_method(vis);
|
||||
attrs.extend(inner_attrs.into_iter());
|
||||
(name, node)
|
||||
};
|
||||
|
||||
P(ImplItem {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: mk_sp(lo, self.last_span.hi),
|
||||
ident: name,
|
||||
vis: vis,
|
||||
attrs: attrs,
|
||||
node: node
|
||||
})
|
||||
}
|
||||
|
||||
fn complain_if_pub_macro(&mut self, visa: Visibility, span: Span) {
|
||||
|
@ -4647,15 +4589,10 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Parse a method in a trait impl, starting with `attrs` attributes.
|
||||
pub fn parse_method(&mut self,
|
||||
attrs: Vec<Attribute>,
|
||||
vis: Visibility)
|
||||
-> P<ImplItem> {
|
||||
let lo = self.span.lo;
|
||||
|
||||
/// Parse a method or a macro invocation in a trait impl.
|
||||
fn parse_impl_method(&mut self, vis: Visibility)
|
||||
-> (Ident, Vec<ast::Attribute>, ast::ImplItem_) {
|
||||
// code copied from parse_macro_use_or_failure... abstraction!
|
||||
let (method_, hi, new_attrs, ident) = {
|
||||
if !self.token.is_any_keyword()
|
||||
&& self.look_ahead(1, |t| *t == token::Not)
|
||||
&& (self.look_ahead(2, |t| *t == token::OpenDelim(token::Paren))
|
||||
|
@ -4680,8 +4617,7 @@ impl<'a> Parser<'a> {
|
|||
if delim != token::Brace {
|
||||
self.expect(&token::Semi)
|
||||
}
|
||||
(ast::MacImplItem(m), self.span.hi, attrs,
|
||||
token::special_idents::invalid)
|
||||
(token::special_idents::invalid, vec![], ast::MacImplItem(m))
|
||||
} else {
|
||||
let unsafety = self.parse_unsafety();
|
||||
let abi = if self.eat_keyword(keywords::Extern) {
|
||||
|
@ -4697,26 +4633,14 @@ impl<'a> Parser<'a> {
|
|||
});
|
||||
self.parse_where_clause(&mut generics);
|
||||
let (inner_attrs, body) = self.parse_inner_attrs_and_block();
|
||||
let body_span = body.span;
|
||||
let mut new_attrs = attrs;
|
||||
new_attrs.push_all(&inner_attrs[..]);
|
||||
(MethodImplItem(ast::MethodSig {
|
||||
(ident, inner_attrs, MethodImplItem(ast::MethodSig {
|
||||
generics: generics,
|
||||
abi: abi,
|
||||
explicit_self: explicit_self,
|
||||
unsafety: unsafety,
|
||||
decl: decl
|
||||
}, body), body_span.hi, new_attrs, ident)
|
||||
}, body))
|
||||
}
|
||||
};
|
||||
P(ImplItem {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
attrs: new_attrs,
|
||||
vis: vis,
|
||||
ident: ident,
|
||||
node: method_,
|
||||
span: mk_sp(lo, hi),
|
||||
})
|
||||
}
|
||||
|
||||
/// Parse trait Foo { ... }
|
||||
|
@ -4747,28 +4671,6 @@ impl<'a> Parser<'a> {
|
|||
(ident, ItemTrait(unsafety, tps, bounds, meths), None)
|
||||
}
|
||||
|
||||
fn parse_impl_items(&mut self) -> (Vec<P<ImplItem>>, Vec<Attribute>) {
|
||||
let mut impl_items = Vec::new();
|
||||
self.expect(&token::OpenDelim(token::Brace));
|
||||
let (inner_attrs, mut method_attrs) =
|
||||
self.parse_inner_attrs_and_next();
|
||||
loop {
|
||||
method_attrs.extend(self.parse_outer_attributes().into_iter());
|
||||
if method_attrs.is_empty() && self.eat(&token::CloseDelim(token::Brace)) {
|
||||
break;
|
||||
}
|
||||
|
||||
let vis = self.parse_visibility();
|
||||
impl_items.push(if self.eat_keyword(keywords::Type) {
|
||||
self.parse_assoc_ty_in_impl(method_attrs, vis)
|
||||
} else {
|
||||
self.parse_method(method_attrs, vis)
|
||||
});
|
||||
method_attrs = vec![];
|
||||
}
|
||||
(impl_items, inner_attrs)
|
||||
}
|
||||
|
||||
/// Parses items implementations variants
|
||||
/// impl<T> Foo { ... }
|
||||
/// impl<T> ToString for &'static T { ... }
|
||||
|
@ -4835,7 +4737,14 @@ impl<'a> Parser<'a> {
|
|||
ty = self.parse_ty_sum();
|
||||
}
|
||||
self.parse_where_clause(&mut generics);
|
||||
let (impl_items, attrs) = self.parse_impl_items();
|
||||
|
||||
self.expect(&token::OpenDelim(token::Brace));
|
||||
let attrs = self.parse_inner_attributes();
|
||||
|
||||
let mut impl_items = vec![];
|
||||
while !self.eat(&token::CloseDelim(token::Brace)) {
|
||||
impl_items.push(self.parse_impl_item());
|
||||
}
|
||||
|
||||
(ast_util::impl_pretty_name(&opt_trait, Some(&*ty)),
|
||||
ItemImpl(unsafety, polarity, generics, opt_trait, ty, impl_items),
|
||||
|
@ -5074,53 +4983,16 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Given a termination token and a vector of already-parsed
|
||||
/// attributes (of length 0 or 1), parse all of the items in a module
|
||||
fn parse_mod_items(&mut self,
|
||||
term: token::Token,
|
||||
first_item_attrs: Vec<Attribute>,
|
||||
inner_lo: BytePos)
|
||||
-> Mod {
|
||||
// Parse all of the items up to closing or an attribute.
|
||||
|
||||
let mut attrs = first_item_attrs;
|
||||
attrs.push_all(&self.parse_outer_attributes());
|
||||
/// Given a termination token, parse all of the items in a module
|
||||
fn parse_mod_items(&mut self, term: &token::Token, inner_lo: BytePos) -> Mod {
|
||||
let mut items = vec![];
|
||||
|
||||
loop {
|
||||
match self.parse_item_(attrs, true) {
|
||||
Err(returned_attrs) => {
|
||||
attrs = returned_attrs;
|
||||
break
|
||||
}
|
||||
Ok(item) => {
|
||||
attrs = self.parse_outer_attributes();
|
||||
items.push(item)
|
||||
}
|
||||
}
|
||||
while let Some(item) = self.parse_item() {
|
||||
items.push(item);
|
||||
}
|
||||
|
||||
// don't think this other loop is even necessary....
|
||||
|
||||
while self.token != term {
|
||||
let mut attrs = mem::replace(&mut attrs, vec![]);
|
||||
attrs.push_all(&self.parse_outer_attributes());
|
||||
debug!("parse_mod_items: parse_item_(attrs={:?})", attrs);
|
||||
match self.parse_item_(attrs, true /* macros allowed */) {
|
||||
Ok(item) => items.push(item),
|
||||
Err(_) => {
|
||||
if !self.eat(term) {
|
||||
let token_str = self.this_token_to_string();
|
||||
self.fatal(&format!("expected item, found `{}`",
|
||||
token_str))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !attrs.is_empty() {
|
||||
// We parsed attributes for the first item but didn't find it
|
||||
let last_span = self.last_span;
|
||||
self.span_err(last_span,
|
||||
Parser::expected_item_err(&attrs[..]));
|
||||
self.fatal(&format!("expected item, found `{}`", token_str))
|
||||
}
|
||||
|
||||
ast::Mod {
|
||||
|
@ -5158,12 +5030,11 @@ impl<'a> Parser<'a> {
|
|||
let mod_inner_lo = self.span.lo;
|
||||
let old_owns_directory = self.owns_directory;
|
||||
self.owns_directory = true;
|
||||
let (inner, next) = self.parse_inner_attrs_and_next();
|
||||
let m = self.parse_mod_items(token::CloseDelim(token::Brace), next, mod_inner_lo);
|
||||
self.expect(&token::CloseDelim(token::Brace));
|
||||
let attrs = self.parse_inner_attributes();
|
||||
let m = self.parse_mod_items(&token::CloseDelim(token::Brace), mod_inner_lo);
|
||||
self.owns_directory = old_owns_directory;
|
||||
self.pop_mod_path();
|
||||
(id, ItemMod(m), Some(inner))
|
||||
(id, ItemMod(m), Some(attrs))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5290,11 +5161,10 @@ impl<'a> Parser<'a> {
|
|||
Some(name),
|
||||
id_sp);
|
||||
let mod_inner_lo = p0.span.lo;
|
||||
let (mod_attrs, next) = p0.parse_inner_attrs_and_next();
|
||||
let first_item_outer_attrs = next;
|
||||
let m0 = p0.parse_mod_items(token::Eof, first_item_outer_attrs, mod_inner_lo);
|
||||
let mod_attrs = p0.parse_inner_attributes();
|
||||
let m0 = p0.parse_mod_items(&token::Eof, mod_inner_lo);
|
||||
self.sess.included_mod_stack.borrow_mut().pop();
|
||||
return (ast::ItemMod(m0), mod_attrs);
|
||||
(ast::ItemMod(m0), mod_attrs)
|
||||
}
|
||||
|
||||
/// Parse a function declaration from a foreign module
|
||||
|
@ -5341,20 +5211,6 @@ impl<'a> Parser<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
/// At this point, this is essentially a wrapper for
|
||||
/// parse_foreign_items.
|
||||
fn parse_foreign_mod_items(&mut self,
|
||||
abi: abi::Abi,
|
||||
first_item_attrs: Vec<Attribute>)
|
||||
-> ForeignMod {
|
||||
let foreign_items = self.parse_foreign_items(first_item_attrs);
|
||||
assert!(self.token == token::CloseDelim(token::Brace));
|
||||
ast::ForeignMod {
|
||||
abi: abi,
|
||||
items: foreign_items
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse extern crate links
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -5433,24 +5289,31 @@ impl<'a> Parser<'a> {
|
|||
lo: BytePos,
|
||||
opt_abi: Option<abi::Abi>,
|
||||
visibility: Visibility,
|
||||
attrs: Vec<Attribute>)
|
||||
mut attrs: Vec<Attribute>)
|
||||
-> P<Item> {
|
||||
|
||||
self.expect(&token::OpenDelim(token::Brace));
|
||||
|
||||
let abi = opt_abi.unwrap_or(abi::C);
|
||||
|
||||
let (inner, next) = self.parse_inner_attrs_and_next();
|
||||
let m = self.parse_foreign_mod_items(abi, next);
|
||||
attrs.extend(self.parse_inner_attributes().into_iter());
|
||||
|
||||
let mut foreign_items = vec![];
|
||||
while let Some(item) = self.parse_foreign_item() {
|
||||
foreign_items.push(item);
|
||||
}
|
||||
self.expect(&token::CloseDelim(token::Brace));
|
||||
|
||||
let last_span = self.last_span;
|
||||
let m = ast::ForeignMod {
|
||||
abi: abi,
|
||||
items: foreign_items
|
||||
};
|
||||
self.mk_item(lo,
|
||||
last_span.hi,
|
||||
special_idents::invalid,
|
||||
ItemForeignMod(m),
|
||||
visibility,
|
||||
maybe_append(attrs, Some(inner)))
|
||||
attrs)
|
||||
}
|
||||
|
||||
/// Parse type Foo = Bar;
|
||||
|
@ -5592,12 +5455,11 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Parse one of the items allowed by the flags; on failure,
|
||||
/// return `Err(remaining_attrs)`.
|
||||
/// Parse one of the items allowed by the flags.
|
||||
/// NB: this function no longer parses the items inside an
|
||||
/// extern crate.
|
||||
fn parse_item_(&mut self, attrs: Vec<Attribute>,
|
||||
macros_allowed: bool) -> MaybeItem {
|
||||
macros_allowed: bool) -> Option<P<Item>> {
|
||||
let nt_item = match self.token {
|
||||
token::Interpolated(token::NtItem(ref item)) => {
|
||||
Some((**item).clone())
|
||||
|
@ -5610,7 +5472,7 @@ impl<'a> Parser<'a> {
|
|||
let mut attrs = attrs;
|
||||
mem::swap(&mut item.attrs, &mut attrs);
|
||||
item.attrs.extend(attrs.into_iter());
|
||||
return Ok(P(item));
|
||||
return Some(P(item));
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
|
@ -5631,12 +5493,12 @@ impl<'a> Parser<'a> {
|
|||
item_,
|
||||
visibility,
|
||||
attrs);
|
||||
return Ok(item);
|
||||
return Some(item);
|
||||
}
|
||||
|
||||
if self.eat_keyword(keywords::Extern) {
|
||||
if self.eat_keyword(keywords::Crate) {
|
||||
return Ok(self.parse_item_extern_crate(lo, visibility, attrs));
|
||||
return Some(self.parse_item_extern_crate(lo, visibility, attrs));
|
||||
}
|
||||
|
||||
let opt_abi = self.parse_opt_abi();
|
||||
|
@ -5653,9 +5515,9 @@ impl<'a> Parser<'a> {
|
|||
item_,
|
||||
visibility,
|
||||
maybe_append(attrs, extra_attrs));
|
||||
return Ok(item);
|
||||
return Some(item);
|
||||
} else if self.check(&token::OpenDelim(token::Brace)) {
|
||||
return Ok(self.parse_item_foreign_mod(lo, opt_abi, visibility, attrs));
|
||||
return Some(self.parse_item_foreign_mod(lo, opt_abi, visibility, attrs));
|
||||
}
|
||||
|
||||
let span = self.span;
|
||||
|
@ -5681,7 +5543,7 @@ impl<'a> Parser<'a> {
|
|||
item_,
|
||||
visibility,
|
||||
maybe_append(attrs, extra_attrs));
|
||||
return Ok(item);
|
||||
return Some(item);
|
||||
}
|
||||
if self.eat_keyword(keywords::Const) {
|
||||
// CONST ITEM
|
||||
|
@ -5698,7 +5560,7 @@ impl<'a> Parser<'a> {
|
|||
item_,
|
||||
visibility,
|
||||
maybe_append(attrs, extra_attrs));
|
||||
return Ok(item);
|
||||
return Some(item);
|
||||
}
|
||||
if self.check_keyword(keywords::Unsafe) &&
|
||||
self.look_ahead(1, |t| t.is_keyword(keywords::Trait))
|
||||
|
@ -5715,7 +5577,7 @@ impl<'a> Parser<'a> {
|
|||
item_,
|
||||
visibility,
|
||||
maybe_append(attrs, extra_attrs));
|
||||
return Ok(item);
|
||||
return Some(item);
|
||||
}
|
||||
if self.check_keyword(keywords::Unsafe) &&
|
||||
self.look_ahead(1, |t| t.is_keyword(keywords::Impl))
|
||||
|
@ -5731,7 +5593,7 @@ impl<'a> Parser<'a> {
|
|||
item_,
|
||||
visibility,
|
||||
maybe_append(attrs, extra_attrs));
|
||||
return Ok(item);
|
||||
return Some(item);
|
||||
}
|
||||
if self.check_keyword(keywords::Fn) {
|
||||
// FUNCTION ITEM
|
||||
|
@ -5745,7 +5607,7 @@ impl<'a> Parser<'a> {
|
|||
item_,
|
||||
visibility,
|
||||
maybe_append(attrs, extra_attrs));
|
||||
return Ok(item);
|
||||
return Some(item);
|
||||
}
|
||||
if self.check_keyword(keywords::Unsafe)
|
||||
&& self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace)) {
|
||||
|
@ -5766,7 +5628,7 @@ impl<'a> Parser<'a> {
|
|||
item_,
|
||||
visibility,
|
||||
maybe_append(attrs, extra_attrs));
|
||||
return Ok(item);
|
||||
return Some(item);
|
||||
}
|
||||
if self.eat_keyword(keywords::Mod) {
|
||||
// MODULE ITEM
|
||||
|
@ -5779,7 +5641,7 @@ impl<'a> Parser<'a> {
|
|||
item_,
|
||||
visibility,
|
||||
maybe_append(attrs, extra_attrs));
|
||||
return Ok(item);
|
||||
return Some(item);
|
||||
}
|
||||
if self.eat_keyword(keywords::Type) {
|
||||
// TYPE ITEM
|
||||
|
@ -5791,7 +5653,7 @@ impl<'a> Parser<'a> {
|
|||
item_,
|
||||
visibility,
|
||||
maybe_append(attrs, extra_attrs));
|
||||
return Ok(item);
|
||||
return Some(item);
|
||||
}
|
||||
if self.eat_keyword(keywords::Enum) {
|
||||
// ENUM ITEM
|
||||
|
@ -5803,7 +5665,7 @@ impl<'a> Parser<'a> {
|
|||
item_,
|
||||
visibility,
|
||||
maybe_append(attrs, extra_attrs));
|
||||
return Ok(item);
|
||||
return Some(item);
|
||||
}
|
||||
if self.eat_keyword(keywords::Trait) {
|
||||
// TRAIT ITEM
|
||||
|
@ -5816,7 +5678,7 @@ impl<'a> Parser<'a> {
|
|||
item_,
|
||||
visibility,
|
||||
maybe_append(attrs, extra_attrs));
|
||||
return Ok(item);
|
||||
return Some(item);
|
||||
}
|
||||
if self.eat_keyword(keywords::Impl) {
|
||||
// IMPL ITEM
|
||||
|
@ -5828,7 +5690,7 @@ impl<'a> Parser<'a> {
|
|||
item_,
|
||||
visibility,
|
||||
maybe_append(attrs, extra_attrs));
|
||||
return Ok(item);
|
||||
return Some(item);
|
||||
}
|
||||
if self.eat_keyword(keywords::Struct) {
|
||||
// STRUCT ITEM
|
||||
|
@ -5840,31 +5702,35 @@ impl<'a> Parser<'a> {
|
|||
item_,
|
||||
visibility,
|
||||
maybe_append(attrs, extra_attrs));
|
||||
return Ok(item);
|
||||
return Some(item);
|
||||
}
|
||||
self.parse_macro_use_or_failure(attrs,macros_allowed,lo,visibility)
|
||||
}
|
||||
|
||||
/// Parse a foreign item; on failure, return `Err(remaining_attrs)`.
|
||||
fn parse_foreign_item(&mut self, attrs: Vec<Attribute>)
|
||||
-> Result<P<ForeignItem>, Vec<Attribute>> {
|
||||
/// Parse a foreign item.
|
||||
fn parse_foreign_item(&mut self) -> Option<P<ForeignItem>> {
|
||||
let lo = self.span.lo;
|
||||
|
||||
let attrs = self.parse_outer_attributes();
|
||||
let visibility = self.parse_visibility();
|
||||
|
||||
if self.check_keyword(keywords::Static) {
|
||||
// FOREIGN STATIC ITEM
|
||||
return Ok(self.parse_item_foreign_static(visibility, attrs));
|
||||
return Some(self.parse_item_foreign_static(visibility, attrs));
|
||||
}
|
||||
if self.check_keyword(keywords::Fn) || self.check_keyword(keywords::Unsafe) {
|
||||
// FOREIGN FUNCTION ITEM
|
||||
return Ok(self.parse_item_foreign_fn(visibility, attrs));
|
||||
return Some(self.parse_item_foreign_fn(visibility, attrs));
|
||||
}
|
||||
|
||||
// FIXME #5668: this will occur for a macro invocation:
|
||||
let item = try!(self.parse_macro_use_or_failure(attrs, true, lo, visibility));
|
||||
match self.parse_macro_use_or_failure(attrs, true, lo, visibility) {
|
||||
Some(item) => {
|
||||
self.span_fatal(item.span, "macros cannot expand to foreign items");
|
||||
}
|
||||
None => None
|
||||
}
|
||||
}
|
||||
|
||||
/// This is the fall-through for parsing items.
|
||||
fn parse_macro_use_or_failure(
|
||||
|
@ -5873,7 +5739,7 @@ impl<'a> Parser<'a> {
|
|||
macros_allowed: bool,
|
||||
lo: BytePos,
|
||||
visibility: Visibility
|
||||
) -> MaybeItem {
|
||||
) -> Option<P<Item>> {
|
||||
if macros_allowed && !self.token.is_any_keyword()
|
||||
&& self.look_ahead(1, |t| *t == token::Not)
|
||||
&& (self.look_ahead(2, |t| t.is_plain_ident())
|
||||
|
@ -5925,7 +5791,7 @@ impl<'a> Parser<'a> {
|
|||
item_,
|
||||
visibility,
|
||||
attrs);
|
||||
return Ok(item);
|
||||
return Some(item);
|
||||
}
|
||||
|
||||
// FAILURE TO PARSE ITEM
|
||||
|
@ -5936,16 +5802,22 @@ impl<'a> Parser<'a> {
|
|||
self.span_fatal(last_span, "unmatched visibility `pub`");
|
||||
}
|
||||
}
|
||||
Err(attrs)
|
||||
|
||||
if !attrs.is_empty() {
|
||||
self.expected_item_err(&attrs);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
// HACK(eddyb) staging required for `quote_item!`.
|
||||
#[cfg(stage0)] // SNAP 270a677
|
||||
pub fn parse_item_with_outer_attributes(&mut self) -> Option<P<Item>> {
|
||||
let attrs = self.parse_outer_attributes();
|
||||
self.parse_item(attrs)
|
||||
self.parse_item()
|
||||
}
|
||||
|
||||
pub fn parse_item(&mut self, attrs: Vec<Attribute>) -> Option<P<Item>> {
|
||||
self.parse_item_(attrs, true).ok()
|
||||
pub fn parse_item(&mut self) -> Option<P<Item>> {
|
||||
let attrs = self.parse_outer_attributes();
|
||||
self.parse_item_(attrs, true)
|
||||
}
|
||||
|
||||
/// Matches view_path : MOD? non_global_path as IDENT
|
||||
|
@ -6051,52 +5923,13 @@ impl<'a> Parser<'a> {
|
|||
P(spanned(lo, self.last_span.hi, ViewPathSimple(rename_to, path)))
|
||||
}
|
||||
|
||||
/// Parses a sequence of foreign items. Stops when it finds program
|
||||
/// text that can't be parsed as an item
|
||||
fn parse_foreign_items(&mut self, first_item_attrs: Vec<Attribute>)
|
||||
-> Vec<P<ForeignItem>> {
|
||||
let mut attrs = first_item_attrs;
|
||||
attrs.push_all(&self.parse_outer_attributes());
|
||||
let mut foreign_items = Vec::new();
|
||||
loop {
|
||||
match self.parse_foreign_item(attrs) {
|
||||
Ok(foreign_item) => {
|
||||
foreign_items.push(foreign_item);
|
||||
}
|
||||
Err(returned_attrs) => {
|
||||
if self.check(&token::CloseDelim(token::Brace)) {
|
||||
attrs = returned_attrs;
|
||||
break
|
||||
}
|
||||
self.unexpected();
|
||||
}
|
||||
}
|
||||
attrs = self.parse_outer_attributes();
|
||||
}
|
||||
|
||||
if !attrs.is_empty() {
|
||||
let last_span = self.last_span;
|
||||
self.span_err(last_span,
|
||||
Parser::expected_item_err(&attrs[..]));
|
||||
}
|
||||
|
||||
foreign_items
|
||||
}
|
||||
|
||||
/// Parses a source module as a crate. This is the main
|
||||
/// entry point for the parser.
|
||||
pub fn parse_crate_mod(&mut self) -> Crate {
|
||||
let lo = self.span.lo;
|
||||
// parse the crate's inner attrs, maybe (oops) one
|
||||
// of the attrs of an item:
|
||||
let (inner, next) = self.parse_inner_attrs_and_next();
|
||||
let first_item_outer_attrs = next;
|
||||
// parse the items inside the crate:
|
||||
let m = self.parse_mod_items(token::Eof, first_item_outer_attrs, lo);
|
||||
|
||||
ast::Crate {
|
||||
module: m,
|
||||
attrs: inner,
|
||||
attrs: self.parse_inner_attributes(),
|
||||
module: self.parse_mod_items(&token::Eof, lo),
|
||||
config: self.cfg.clone(),
|
||||
span: mk_sp(lo, self.span.lo),
|
||||
exported_macros: Vec::new(),
|
||||
|
|
|
@ -58,14 +58,14 @@ pub fn string_to_expr (source_str : String) -> P<ast::Expr> {
|
|||
/// Parse a string, return an item
|
||||
pub fn string_to_item (source_str : String) -> Option<P<ast::Item>> {
|
||||
with_error_checking_parse(source_str, |p| {
|
||||
p.parse_item(Vec::new())
|
||||
p.parse_item()
|
||||
})
|
||||
}
|
||||
|
||||
/// Parse a string, return a stmt
|
||||
pub fn string_to_stmt(source_str : String) -> P<ast::Stmt> {
|
||||
with_error_checking_parse(source_str, |p| {
|
||||
p.parse_stmt(Vec::new())
|
||||
p.parse_stmt().unwrap()
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -8,4 +8,4 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
# //~ ERROR 11:1: 11:2 error: expected one of `!` or `[`, found `<eof>`
|
||||
# //~ ERROR 11:1: 11:2 error: expected `[`, found `<eof>`
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// error-pattern:expected one of `!` or `[`, found `vec`
|
||||
// error-pattern:expected `[`, found `vec`
|
||||
mod blade_runner {
|
||||
#vec[doc(
|
||||
brief = "Blade Runner is probably the best movie ever",
|
||||
|
|
|
@ -25,7 +25,7 @@ fn syntax_extension(cx: &ExtCtxt) {
|
|||
let a: P<syntax::ast::Expr> = quote_expr!(cx, 1 + 2);
|
||||
let _b: Option<P<syntax::ast::Item>> = quote_item!(cx, static foo : int = $e_toks; );
|
||||
let _c: P<syntax::ast::Pat> = quote_pat!(cx, (x, 1 .. 4, *) );
|
||||
let _d: P<syntax::ast::Stmt> = quote_stmt!(cx, let x = $a; );
|
||||
let _d: Option<P<syntax::ast::Stmt>> = quote_stmt!(cx, let x = $a; );
|
||||
let _d: syntax::ast::Arm = quote_arm!(cx, (ref x, ref y) = (x, y) );
|
||||
let _e: P<syntax::ast::Expr> = quote_expr!(cx, match foo { $p_toks => 10 } );
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue