syntax: merge ast::ViewItem into ast::Item.

This commit is contained in:
Eduard Burtescu 2014-12-23 15:07:30 +02:00
parent 53edd767b4
commit 38ac9e3984
2 changed files with 130 additions and 353 deletions

View file

@ -53,7 +53,6 @@ pub use self::UnboxedClosureKind::*;
pub use self::UnOp::*; pub use self::UnOp::*;
pub use self::UnsafeSource::*; pub use self::UnsafeSource::*;
pub use self::VariantKind::*; pub use self::VariantKind::*;
pub use self::ViewItem_::*;
pub use self::ViewPath_::*; pub use self::ViewPath_::*;
pub use self::Visibility::*; pub use self::Visibility::*;
pub use self::PathParameters::*; pub use self::PathParameters::*;
@ -511,7 +510,6 @@ impl PartialEq for MetaItem_ {
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)]
pub struct Block { pub struct Block {
pub view_items: Vec<ViewItem>,
pub stmts: Vec<P<Stmt>>, pub stmts: Vec<P<Stmt>>,
pub expr: Option<P<Expr>>, pub expr: Option<P<Expr>>,
pub id: NodeId, pub id: NodeId,
@ -1452,14 +1450,12 @@ pub struct Mod {
/// For `mod foo;`, the inner span ranges from the first token /// For `mod foo;`, the inner span ranges from the first token
/// to the last token in the external file. /// to the last token in the external file.
pub inner: Span, pub inner: Span,
pub view_items: Vec<ViewItem>,
pub items: Vec<P<Item>>, pub items: Vec<P<Item>>,
} }
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)]
pub struct ForeignMod { pub struct ForeignMod {
pub abi: Abi, pub abi: Abi,
pub view_items: Vec<ViewItem>,
pub items: Vec<P<ForeignItem>>, pub items: Vec<P<ForeignItem>>,
} }
@ -1518,44 +1514,13 @@ pub enum ViewPath_ {
/// or just /// or just
/// ///
/// `foo::bar::baz` (with `as baz` implicitly on the right) /// `foo::bar::baz` (with `as baz` implicitly on the right)
ViewPathSimple(Ident, Path, NodeId), ViewPathSimple(Ident, Path),
/// `foo::bar::*` /// `foo::bar::*`
ViewPathGlob(Path, NodeId), ViewPathGlob(Path),
/// `foo::bar::{a,b,c}` /// `foo::bar::{a,b,c}`
ViewPathList(Path, Vec<PathListItem> , NodeId) ViewPathList(Path, Vec<PathListItem>)
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)]
pub struct ViewItem {
pub node: ViewItem_,
pub attrs: Vec<Attribute>,
pub vis: Visibility,
pub span: Span,
}
impl ViewItem {
pub fn id(&self) -> NodeId {
match self.node {
ViewItemExternCrate(_, _, id) => id,
ViewItemUse(ref vp) => match vp.node {
ViewPathSimple(_, _, id) => id,
ViewPathGlob(_, id) => id,
ViewPathList(_, _, id) => id,
}
}
}
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)]
pub enum ViewItem_ {
/// Ident: name used to refer to this crate in the code
/// optional (InternedString,StrStyle): if present, this is a location
/// (containing arbitrary characters) from which to fetch the crate sources
/// For example, extern crate whatever = "github.com/rust-lang/rust"
ViewItemExternCrate(Ident, Option<(InternedString,StrStyle)>, NodeId),
ViewItemUse(P<ViewPath>),
} }
/// Meta-data associated with an item /// Meta-data associated with an item
@ -1677,6 +1642,12 @@ pub struct Item {
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)]
pub enum Item_ { pub enum Item_ {
// Optional location (containing arbitrary characters) from which
// to fetch the crate sources.
// For example, extern crate whatever = "github.com/rust-lang/rust".
ItemExternCrate(Option<(InternedString, StrStyle)>),
ItemUse(P<ViewPath>),
ItemStatic(P<Ty>, Mutability, P<Expr>), ItemStatic(P<Ty>, Mutability, P<Expr>),
ItemConst(P<Ty>, P<Expr>), ItemConst(P<Ty>, P<Expr>),
ItemFn(P<FnDecl>, Unsafety, Abi, Generics, P<Block>), ItemFn(P<FnDecl>, Unsafety, Abi, Generics, P<Block>),
@ -1703,6 +1674,8 @@ pub enum Item_ {
impl Item_ { impl Item_ {
pub fn descriptive_variant(&self) -> &str { pub fn descriptive_variant(&self) -> &str {
match *self { match *self {
ItemExternCrate(..) => "extern crate",
ItemUse(..) => "use",
ItemStatic(..) => "static item", ItemStatic(..) => "static item",
ItemConst(..) => "constant item", ItemConst(..) => "constant item",
ItemFn(..) => "function", ItemFn(..) => "function",

View file

@ -9,7 +9,6 @@
// except according to those terms. // except according to those terms.
pub use self::PathParsingMode::*; pub use self::PathParsingMode::*;
use self::ItemOrViewItem::*;
use abi; use abi;
use ast::{AssociatedType, BareFnTy}; use ast::{AssociatedType, BareFnTy};
@ -35,6 +34,7 @@ use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod, FunctionRet
use ast::{Ident, Inherited, ImplItem, Item, Item_, ItemStatic}; use ast::{Ident, Inherited, ImplItem, Item, Item_, ItemStatic};
use ast::{ItemEnum, ItemFn, ItemForeignMod, ItemImpl, ItemConst}; use ast::{ItemEnum, ItemFn, ItemForeignMod, ItemImpl, ItemConst};
use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy}; use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy};
use ast::{ItemExternCrate, ItemUse};
use ast::{LifetimeDef, Lit, Lit_}; use ast::{LifetimeDef, Lit, Lit_};
use ast::{LitBool, LitChar, LitByte, LitBinary}; use ast::{LitBool, LitChar, LitByte, LitBinary};
use ast::{LitStr, LitInt, Local, LocalLet}; use ast::{LitStr, LitInt, Local, LocalLet};
@ -59,7 +59,6 @@ use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr, TyQPath
use ast::{TyRptr, TyTup, TyU32, TyVec, UnUniq}; use ast::{TyRptr, TyTup, TyU32, TyVec, UnUniq};
use ast::{TypeImplItem, TypeTraitItem, Typedef, UnboxedClosureKind}; use ast::{TypeImplItem, TypeTraitItem, Typedef, UnboxedClosureKind};
use ast::{UnnamedField, UnsafeBlock}; use ast::{UnnamedField, UnsafeBlock};
use ast::{ViewItem, ViewItem_, ViewItemExternCrate, ViewItemUse};
use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple}; use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
use ast::{Visibility, WhereClause}; use ast::{Visibility, WhereClause};
use ast; use ast;
@ -122,14 +121,9 @@ pub enum BoundParsingMode {
Modified, Modified,
} }
enum ItemOrViewItem { /// The `Err` case indicates a failure to parse any kind of item.
/// Indicates a failure to parse any kind of item. The attributes are /// The attributes are returned.
/// returned. type MaybeItem = Result<P<Item>, Vec<Attribute>>;
IoviNone(Vec<Attribute>),
IoviItem(P<Item>),
IoviForeignItem(P<ForeignItem>),
IoviViewItem(ViewItem)
}
/// Possibly accept an `token::Interpolated` expression (a pre-parsed expression /// Possibly accept an `token::Interpolated` expression (a pre-parsed expression
@ -231,19 +225,6 @@ macro_rules! maybe_whole {
} }
} }
); );
(iovi $p:expr, $constructor:ident) => (
{
let found = match ($p).token {
token::Interpolated(token::$constructor(_)) => {
Some(($p).bump_and_get())
}
_ => None
};
if let Some(token::Interpolated(token::$constructor(x))) = found {
return IoviItem(x.clone());
}
}
);
(pair_empty $p:expr, $constructor:ident) => ( (pair_empty $p:expr, $constructor:ident) => (
{ {
let found = match ($p).token { let found = match ($p).token {
@ -269,14 +250,6 @@ fn maybe_append(mut lhs: Vec<Attribute>, rhs: Option<Vec<Attribute>>)
lhs lhs
} }
struct ParsedItemsAndViewItems {
attrs_remaining: Vec<Attribute>,
view_items: Vec<ViewItem>,
items: Vec<P<Item>> ,
foreign_items: Vec<P<ForeignItem>>
}
/* ident is handled by common.rs */ /* ident is handled by common.rs */
pub struct Parser<'a> { pub struct Parser<'a> {
@ -3032,8 +3005,7 @@ impl<'a> Parser<'a> {
let body = self.parse_expr(); let body = self.parse_expr();
let fakeblock = P(ast::Block { let fakeblock = P(ast::Block {
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
view_items: Vec::new(), stmts: vec![],
stmts: Vec::new(),
span: body.span, span: body.span,
expr: Some(body), expr: Some(body),
rules: DefaultBlock, rules: DefaultBlock,
@ -3731,20 +3703,13 @@ impl<'a> Parser<'a> {
} else { } else {
let found_attrs = !item_attrs.is_empty(); let found_attrs = !item_attrs.is_empty();
let item_err = Parser::expected_item_err(&item_attrs[]); let item_err = Parser::expected_item_err(&item_attrs[]);
match self.parse_item_or_view_item(item_attrs, false) { match self.parse_item_(item_attrs, false) {
IoviItem(i) => { Ok(i) => {
let hi = i.span.hi; let hi = i.span.hi;
let decl = P(spanned(lo, hi, DeclItem(i))); let decl = P(spanned(lo, hi, DeclItem(i)));
P(spanned(lo, hi, StmtDecl(decl, ast::DUMMY_NODE_ID))) P(spanned(lo, hi, StmtDecl(decl, ast::DUMMY_NODE_ID)))
} }
IoviViewItem(vi) => { Err(_) => {
self.span_fatal(vi.span,
"view items must be declared at the top of the block");
}
IoviForeignItem(_) => {
self.fatal("foreign items are not allowed here");
}
IoviNone(_) => {
if found_attrs { if found_attrs {
let last_span = self.last_span; let last_span = self.last_span;
self.span_err(last_span, item_err); self.span_err(last_span, item_err);
@ -3794,36 +3759,17 @@ impl<'a> Parser<'a> {
(inner, self.parse_block_tail_(lo, DefaultBlock, next)) (inner, self.parse_block_tail_(lo, DefaultBlock, next))
} }
/// Precondition: already parsed the '{' or '#{' /// Precondition: already parsed the '{'.
/// I guess that also means "already parsed the 'impure'" if
/// necessary, and this should take a qualifier.
/// Some blocks start with "#{"...
fn parse_block_tail(&mut self, lo: BytePos, s: BlockCheckMode) -> P<Block> { fn parse_block_tail(&mut self, lo: BytePos, s: BlockCheckMode) -> P<Block> {
self.parse_block_tail_(lo, s, Vec::new()) self.parse_block_tail_(lo, s, Vec::new())
} }
/// Parse the rest of a block expression or function body /// Parse the rest of a block expression or function body
fn parse_block_tail_(&mut self, lo: BytePos, s: BlockCheckMode, fn parse_block_tail_(&mut self, lo: BytePos, s: BlockCheckMode,
first_item_attrs: Vec<Attribute> ) -> P<Block> { first_item_attrs: Vec<Attribute>) -> P<Block> {
let mut stmts = Vec::new(); let mut stmts = vec![];
let mut expr = None; let mut expr = None;
let mut attributes_box = first_item_attrs;
// wouldn't it be more uniform to parse view items only, here?
let ParsedItemsAndViewItems {
attrs_remaining,
view_items,
items,
..
} = self.parse_items_and_view_items(first_item_attrs,
false, false);
for item in items.into_iter() {
let span = item.span;
let decl = P(spanned(span.lo, span.hi, DeclItem(item)));
stmts.push(P(spanned(span.lo, span.hi, StmtDecl(decl, ast::DUMMY_NODE_ID))));
}
let mut attributes_box = attrs_remaining;
while self.token != token::CloseDelim(token::Brace) { while self.token != token::CloseDelim(token::Brace) {
// parsing items even when they're not allowed lets us give // parsing items even when they're not allowed lets us give
@ -3932,7 +3878,6 @@ impl<'a> Parser<'a> {
let hi = self.span.hi; let hi = self.span.hi;
self.bump(); self.bump();
P(ast::Block { P(ast::Block {
view_items: view_items,
stmts: stmts, stmts: stmts,
expr: expr, expr: expr,
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
@ -5031,39 +4976,34 @@ impl<'a> Parser<'a> {
first_item_attrs: Vec<Attribute>, first_item_attrs: Vec<Attribute>,
inner_lo: BytePos) inner_lo: BytePos)
-> Mod { -> Mod {
// parse all of the items up to closing or an attribute. // Parse all of the items up to closing or an attribute.
// view items are legal here.
let ParsedItemsAndViewItems { let mut attrs = first_item_attrs;
attrs_remaining, attrs.push_all(&self.parse_outer_attributes()[]);
view_items, let mut items = vec![];
items: starting_items,
.. loop {
} = self.parse_items_and_view_items(first_item_attrs, true, true); match self.parse_item_(attrs, true) {
let mut items: Vec<P<Item>> = starting_items; Err(returned_attrs) => {
let attrs_remaining_len = attrs_remaining.len(); attrs = returned_attrs;
break
}
Ok(item) => {
attrs = self.parse_outer_attributes();
items.push(item)
}
}
}
// don't think this other loop is even necessary.... // don't think this other loop is even necessary....
let mut first = true;
while self.token != term { while self.token != term {
let mut attrs = self.parse_outer_attributes(); let mut attrs = mem::replace(&mut attrs, vec![]);
if first { attrs.push_all(&self.parse_outer_attributes()[]);
let mut tmp = attrs_remaining.clone(); debug!("parse_mod_items: parse_item_(attrs={:?})", attrs);
tmp.push_all(&attrs[]); match self.parse_item_(attrs, true /* macros allowed */) {
attrs = tmp; Ok(item) => items.push(item),
first = false; Err(_) => {
}
debug!("parse_mod_items: parse_item_or_view_item(attrs={:?})",
attrs);
match self.parse_item_or_view_item(attrs,
true /* macros allowed */) {
IoviItem(item) => items.push(item),
IoviViewItem(view_item) => {
self.span_fatal(view_item.span,
"view items must be declared at the top of \
the module");
}
_ => {
let token_str = self.this_token_to_string(); let token_str = self.this_token_to_string();
self.fatal(&format!("expected item, found `{}`", self.fatal(&format!("expected item, found `{}`",
token_str)[]) token_str)[])
@ -5071,16 +5011,15 @@ impl<'a> Parser<'a> {
} }
} }
if first && attrs_remaining_len > 0u { if !attrs.is_empty() {
// We parsed attributes for the first item but didn't find it // We parsed attributes for the first item but didn't find it
let last_span = self.last_span; let last_span = self.last_span;
self.span_err(last_span, self.span_err(last_span,
Parser::expected_item_err(&attrs_remaining[])); Parser::expected_item_err(&attrs[]));
} }
ast::Mod { ast::Mod {
inner: mk_sp(inner_lo, self.span.lo), inner: mk_sp(inner_lo, self.span.lo),
view_items: view_items,
items: items items: items
} }
} }
@ -5298,23 +5237,12 @@ impl<'a> Parser<'a> {
/// parse_foreign_items. /// parse_foreign_items.
fn parse_foreign_mod_items(&mut self, fn parse_foreign_mod_items(&mut self,
abi: abi::Abi, abi: abi::Abi,
first_item_attrs: Vec<Attribute> ) first_item_attrs: Vec<Attribute>)
-> ForeignMod { -> ForeignMod {
let ParsedItemsAndViewItems { let foreign_items = self.parse_foreign_items(first_item_attrs);
attrs_remaining,
view_items,
items: _,
foreign_items,
} = self.parse_foreign_items(first_item_attrs, true);
if !attrs_remaining.is_empty() {
let last_span = self.last_span;
self.span_err(last_span,
Parser::expected_item_err(&attrs_remaining[]));
}
assert!(self.token == token::CloseDelim(token::Brace)); assert!(self.token == token::CloseDelim(token::Brace));
ast::ForeignMod { ast::ForeignMod {
abi: abi, abi: abi,
view_items: view_items,
items: foreign_items items: foreign_items
} }
} }
@ -5329,8 +5257,8 @@ impl<'a> Parser<'a> {
fn parse_item_extern_crate(&mut self, fn parse_item_extern_crate(&mut self,
lo: BytePos, lo: BytePos,
visibility: Visibility, visibility: Visibility,
attrs: Vec<Attribute> ) attrs: Vec<Attribute>)
-> ItemOrViewItem { -> P<Item> {
let span = self.span; let span = self.span;
let (maybe_path, ident) = match self.token { let (maybe_path, ident) = match self.token {
@ -5374,12 +5302,13 @@ impl<'a> Parser<'a> {
} }
}; };
IoviViewItem(ast::ViewItem { let last_span = self.last_span;
node: ViewItemExternCrate(ident, maybe_path, ast::DUMMY_NODE_ID), self.mk_item(lo,
attrs: attrs, last_span.hi,
vis: visibility, ident,
span: mk_sp(lo, self.last_span.hi) ItemExternCrate(maybe_path),
}) visibility,
attrs)
} }
/// Parse `extern` for foreign ABIs /// Parse `extern` for foreign ABIs
@ -5396,8 +5325,8 @@ impl<'a> Parser<'a> {
lo: BytePos, lo: BytePos,
opt_abi: Option<abi::Abi>, opt_abi: Option<abi::Abi>,
visibility: Visibility, visibility: Visibility,
attrs: Vec<Attribute> ) attrs: Vec<Attribute>)
-> ItemOrViewItem { -> P<Item> {
self.expect(&token::OpenDelim(token::Brace)); self.expect(&token::OpenDelim(token::Brace));
@ -5408,13 +5337,12 @@ impl<'a> Parser<'a> {
self.expect(&token::CloseDelim(token::Brace)); self.expect(&token::CloseDelim(token::Brace));
let last_span = self.last_span; let last_span = self.last_span;
let item = self.mk_item(lo, self.mk_item(lo,
last_span.hi, last_span.hi,
special_idents::invalid, special_idents::invalid,
ItemForeignMod(m), ItemForeignMod(m),
visibility, visibility,
maybe_append(attrs, Some(inner))); maybe_append(attrs, Some(inner)))
return IoviItem(item);
} }
/// Parse type Foo = Bar; /// Parse type Foo = Bar;
@ -5556,14 +5484,12 @@ impl<'a> Parser<'a> {
} }
} }
/// Parse one of the items or view items allowed by the /// Parse one of the items allowed by the flags; on failure,
/// flags; on failure, return IoviNone. /// return `Err(remaining_attrs)`.
/// NB: this function no longer parses the items inside an /// NB: this function no longer parses the items inside an
/// extern crate. /// extern crate.
fn parse_item_or_view_item(&mut self, fn parse_item_(&mut self, attrs: Vec<Attribute>,
attrs: Vec<Attribute> , macros_allowed: bool) -> MaybeItem {
macros_allowed: bool)
-> ItemOrViewItem {
let nt_item = match self.token { let nt_item = match self.token {
token::Interpolated(token::NtItem(ref item)) => { token::Interpolated(token::NtItem(ref item)) => {
Some((**item).clone()) Some((**item).clone())
@ -5576,7 +5502,7 @@ impl<'a> Parser<'a> {
let mut attrs = attrs; let mut attrs = attrs;
mem::swap(&mut item.attrs, &mut attrs); mem::swap(&mut item.attrs, &mut attrs);
item.attrs.extend(attrs.into_iter()); item.attrs.extend(attrs.into_iter());
return IoviItem(P(item)); return Ok(P(item));
} }
None => {} None => {}
} }
@ -5585,22 +5511,24 @@ impl<'a> Parser<'a> {
let visibility = self.parse_visibility(); let visibility = self.parse_visibility();
// must be a view item:
if self.eat_keyword(keywords::Use) { if self.eat_keyword(keywords::Use) {
// USE ITEM (IoviViewItem) // USE ITEM
let view_item = self.parse_use(); let item_ = ItemUse(self.parse_view_path());
self.expect(&token::Semi); self.expect(&token::Semi);
return IoviViewItem(ast::ViewItem {
node: view_item, let last_span = self.last_span;
attrs: attrs, let item = self.mk_item(lo,
vis: visibility, last_span.hi,
span: mk_sp(lo, self.last_span.hi) token::special_idents::invalid,
}); item_,
visibility,
attrs);
return Ok(item);
} }
// either a view item or an item:
if self.eat_keyword(keywords::Extern) { if self.eat_keyword(keywords::Extern) {
if self.eat_keyword(keywords::Crate) { if self.eat_keyword(keywords::Crate) {
return self.parse_item_extern_crate(lo, visibility, attrs); return Ok(self.parse_item_extern_crate(lo, visibility, attrs));
} }
let opt_abi = self.parse_opt_abi(); let opt_abi = self.parse_opt_abi();
@ -5617,9 +5545,9 @@ impl<'a> Parser<'a> {
item_, item_,
visibility, visibility,
maybe_append(attrs, extra_attrs)); maybe_append(attrs, extra_attrs));
return IoviItem(item); return Ok(item);
} else if self.check(&token::OpenDelim(token::Brace)) { } else if self.check(&token::OpenDelim(token::Brace)) {
return self.parse_item_foreign_mod(lo, opt_abi, visibility, attrs); return Ok(self.parse_item_foreign_mod(lo, opt_abi, visibility, attrs));
} }
let span = self.span; let span = self.span;
@ -5634,7 +5562,6 @@ impl<'a> Parser<'a> {
self.span_err(span, "`virtual` structs have been removed from the language"); self.span_err(span, "`virtual` structs have been removed from the language");
} }
// the rest are all guaranteed to be items:
if self.token.is_keyword(keywords::Static) { if self.token.is_keyword(keywords::Static) {
// STATIC ITEM // STATIC ITEM
self.bump(); self.bump();
@ -5647,7 +5574,7 @@ impl<'a> Parser<'a> {
item_, item_,
visibility, visibility,
maybe_append(attrs, extra_attrs)); maybe_append(attrs, extra_attrs));
return IoviItem(item); return Ok(item);
} }
if self.token.is_keyword(keywords::Const) { if self.token.is_keyword(keywords::Const) {
// CONST ITEM // CONST ITEM
@ -5665,7 +5592,7 @@ impl<'a> Parser<'a> {
item_, item_,
visibility, visibility,
maybe_append(attrs, extra_attrs)); maybe_append(attrs, extra_attrs));
return IoviItem(item); return Ok(item);
} }
if self.token.is_keyword(keywords::Unsafe) && if self.token.is_keyword(keywords::Unsafe) &&
self.look_ahead(1u, |t| t.is_keyword(keywords::Trait)) self.look_ahead(1u, |t| t.is_keyword(keywords::Trait))
@ -5682,7 +5609,7 @@ impl<'a> Parser<'a> {
item_, item_,
visibility, visibility,
maybe_append(attrs, extra_attrs)); maybe_append(attrs, extra_attrs));
return IoviItem(item); return Ok(item);
} }
if self.token.is_keyword(keywords::Unsafe) && if self.token.is_keyword(keywords::Unsafe) &&
self.look_ahead(1u, |t| t.is_keyword(keywords::Impl)) self.look_ahead(1u, |t| t.is_keyword(keywords::Impl))
@ -5698,7 +5625,7 @@ impl<'a> Parser<'a> {
item_, item_,
visibility, visibility,
maybe_append(attrs, extra_attrs)); maybe_append(attrs, extra_attrs));
return IoviItem(item); return Ok(item);
} }
if self.token.is_keyword(keywords::Fn) { if self.token.is_keyword(keywords::Fn) {
// FUNCTION ITEM // FUNCTION ITEM
@ -5712,7 +5639,7 @@ impl<'a> Parser<'a> {
item_, item_,
visibility, visibility,
maybe_append(attrs, extra_attrs)); maybe_append(attrs, extra_attrs));
return IoviItem(item); return Ok(item);
} }
if self.token.is_keyword(keywords::Unsafe) if self.token.is_keyword(keywords::Unsafe)
&& self.look_ahead(1u, |t| *t != token::OpenDelim(token::Brace)) { && self.look_ahead(1u, |t| *t != token::OpenDelim(token::Brace)) {
@ -5733,7 +5660,7 @@ impl<'a> Parser<'a> {
item_, item_,
visibility, visibility,
maybe_append(attrs, extra_attrs)); maybe_append(attrs, extra_attrs));
return IoviItem(item); return Ok(item);
} }
if self.eat_keyword(keywords::Mod) { if self.eat_keyword(keywords::Mod) {
// MODULE ITEM // MODULE ITEM
@ -5746,7 +5673,7 @@ impl<'a> Parser<'a> {
item_, item_,
visibility, visibility,
maybe_append(attrs, extra_attrs)); maybe_append(attrs, extra_attrs));
return IoviItem(item); return Ok(item);
} }
if self.eat_keyword(keywords::Type) { if self.eat_keyword(keywords::Type) {
// TYPE ITEM // TYPE ITEM
@ -5758,7 +5685,7 @@ impl<'a> Parser<'a> {
item_, item_,
visibility, visibility,
maybe_append(attrs, extra_attrs)); maybe_append(attrs, extra_attrs));
return IoviItem(item); return Ok(item);
} }
if self.eat_keyword(keywords::Enum) { if self.eat_keyword(keywords::Enum) {
// ENUM ITEM // ENUM ITEM
@ -5770,7 +5697,7 @@ impl<'a> Parser<'a> {
item_, item_,
visibility, visibility,
maybe_append(attrs, extra_attrs)); maybe_append(attrs, extra_attrs));
return IoviItem(item); return Ok(item);
} }
if self.eat_keyword(keywords::Trait) { if self.eat_keyword(keywords::Trait) {
// TRAIT ITEM // TRAIT ITEM
@ -5783,7 +5710,7 @@ impl<'a> Parser<'a> {
item_, item_,
visibility, visibility,
maybe_append(attrs, extra_attrs)); maybe_append(attrs, extra_attrs));
return IoviItem(item); return Ok(item);
} }
if self.eat_keyword(keywords::Impl) { if self.eat_keyword(keywords::Impl) {
// IMPL ITEM // IMPL ITEM
@ -5795,7 +5722,7 @@ impl<'a> Parser<'a> {
item_, item_,
visibility, visibility,
maybe_append(attrs, extra_attrs)); maybe_append(attrs, extra_attrs));
return IoviItem(item); return Ok(item);
} }
if self.eat_keyword(keywords::Struct) { if self.eat_keyword(keywords::Struct) {
// STRUCT ITEM // STRUCT ITEM
@ -5807,32 +5734,30 @@ impl<'a> Parser<'a> {
item_, item_,
visibility, visibility,
maybe_append(attrs, extra_attrs)); maybe_append(attrs, extra_attrs));
return IoviItem(item); return Ok(item);
} }
self.parse_macro_use_or_failure(attrs,macros_allowed,lo,visibility) self.parse_macro_use_or_failure(attrs,macros_allowed,lo,visibility)
} }
/// Parse a foreign item; on failure, return IoviNone. /// Parse a foreign item; on failure, return `Err(remaining_attrs)`.
fn parse_foreign_item(&mut self, fn parse_foreign_item(&mut self, attrs: Vec<Attribute>)
attrs: Vec<Attribute> , -> Result<P<ForeignItem>, Vec<Attribute>> {
macros_allowed: bool)
-> ItemOrViewItem {
maybe_whole!(iovi self, NtItem);
let lo = self.span.lo; let lo = self.span.lo;
let visibility = self.parse_visibility(); let visibility = self.parse_visibility();
if self.token.is_keyword(keywords::Static) { if self.token.is_keyword(keywords::Static) {
// FOREIGN STATIC ITEM // FOREIGN STATIC ITEM
let item = self.parse_item_foreign_static(visibility, attrs); return Ok(self.parse_item_foreign_static(visibility, attrs));
return IoviForeignItem(item);
} }
if self.token.is_keyword(keywords::Fn) || self.token.is_keyword(keywords::Unsafe) { if self.token.is_keyword(keywords::Fn) || self.token.is_keyword(keywords::Unsafe) {
// FOREIGN FUNCTION ITEM // FOREIGN FUNCTION ITEM
let item = self.parse_item_foreign_fn(visibility, attrs); return Ok(self.parse_item_foreign_fn(visibility, attrs));
return IoviForeignItem(item);
} }
self.parse_macro_use_or_failure(attrs,macros_allowed,lo,visibility)
// FIXME #5668: this will occur for a macro invocation:
let item = try!(self.parse_macro_use_or_failure(attrs, true, lo, visibility));
self.span_fatal(item.span, "macros cannot expand to foreign items");
} }
/// This is the fall-through for parsing items. /// This is the fall-through for parsing items.
@ -5842,7 +5767,7 @@ impl<'a> Parser<'a> {
macros_allowed: bool, macros_allowed: bool,
lo: BytePos, lo: BytePos,
visibility: Visibility visibility: Visibility
) -> ItemOrViewItem { ) -> MaybeItem {
if macros_allowed && !self.token.is_any_keyword() if macros_allowed && !self.token.is_any_keyword()
&& self.look_ahead(1, |t| *t == token::Not) && self.look_ahead(1, |t| *t == token::Not)
&& (self.look_ahead(2, |t| t.is_plain_ident()) && (self.look_ahead(2, |t| t.is_plain_ident())
@ -5891,7 +5816,7 @@ impl<'a> Parser<'a> {
item_, item_,
visibility, visibility,
attrs); attrs);
return IoviItem(item); return Ok(item);
} }
// FAILURE TO PARSE ITEM // FAILURE TO PARSE ITEM
@ -5902,7 +5827,7 @@ impl<'a> Parser<'a> {
self.span_fatal(last_span, "unmatched visibility `pub`"); self.span_fatal(last_span, "unmatched visibility `pub`");
} }
} }
return IoviNone(attrs); Err(attrs)
} }
pub fn parse_item_with_outer_attributes(&mut self) -> Option<P<Item>> { pub fn parse_item_with_outer_attributes(&mut self) -> Option<P<Item>> {
@ -5911,30 +5836,9 @@ impl<'a> Parser<'a> {
} }
pub fn parse_item(&mut self, attrs: Vec<Attribute>) -> Option<P<Item>> { pub fn parse_item(&mut self, attrs: Vec<Attribute>) -> Option<P<Item>> {
match self.parse_item_or_view_item(attrs, true) { self.parse_item_(attrs, true).ok()
IoviNone(_) => None,
IoviViewItem(_) =>
self.fatal("view items are not allowed here"),
IoviForeignItem(_) =>
self.fatal("foreign items are not allowed here"),
IoviItem(item) => Some(item)
}
} }
/// Parse a ViewItem, e.g. `use foo::bar` or `extern crate foo`
pub fn parse_view_item(&mut self, attrs: Vec<Attribute>) -> ViewItem {
match self.parse_item_or_view_item(attrs, false) {
IoviViewItem(vi) => vi,
_ => self.fatal("expected `use` or `extern crate`"),
}
}
/// Parse, e.g., "use a::b::{z,y}"
fn parse_use(&mut self) -> ViewItem_ {
return ViewItemUse(self.parse_view_path());
}
/// Matches view_path : MOD? non_global_path as IDENT /// Matches view_path : MOD? non_global_path as IDENT
/// | MOD? non_global_path MOD_SEP LBRACE RBRACE /// | MOD? non_global_path MOD_SEP LBRACE RBRACE
/// | MOD? non_global_path MOD_SEP LBRACE ident_seq RBRACE /// | MOD? non_global_path MOD_SEP LBRACE ident_seq RBRACE
@ -5959,8 +5863,7 @@ impl<'a> Parser<'a> {
global: false, global: false,
segments: Vec::new() segments: Vec::new()
}; };
return P(spanned(lo, self.span.hi, return P(spanned(lo, self.span.hi, ViewPathList(path, idents)));
ViewPathList(path, idents, ast::DUMMY_NODE_ID)));
} }
let first_ident = self.parse_ident(); let first_ident = self.parse_ident();
@ -5994,8 +5897,7 @@ impl<'a> Parser<'a> {
} }
}).collect() }).collect()
}; };
return P(spanned(lo, self.span.hi, return P(spanned(lo, self.span.hi, ViewPathList(path, idents)));
ViewPathList(path, idents, ast::DUMMY_NODE_ID)));
} }
// foo::bar::* // foo::bar::*
@ -6011,8 +5913,7 @@ impl<'a> Parser<'a> {
} }
}).collect() }).collect()
}; };
return P(spanned(lo, self.span.hi, return P(spanned(lo, self.span.hi, ViewPathGlob(path)));
ViewPathGlob(path, ast::DUMMY_NODE_ID)));
} }
_ => break _ => break
@ -6033,136 +5934,39 @@ impl<'a> Parser<'a> {
if self.eat_keyword(keywords::As) { if self.eat_keyword(keywords::As) {
rename_to = self.parse_ident() rename_to = self.parse_ident()
} }
P(spanned(lo, P(spanned(lo, self.last_span.hi, ViewPathSimple(rename_to, path)))
self.last_span.hi,
ViewPathSimple(rename_to, path, ast::DUMMY_NODE_ID)))
}
/// Parses a sequence of items. Stops when it finds program
/// text that can't be parsed as an item
/// - mod_items uses extern_mod_allowed = true
/// - block_tail_ uses extern_mod_allowed = false
fn parse_items_and_view_items(&mut self,
first_item_attrs: Vec<Attribute> ,
mut extern_mod_allowed: bool,
macros_allowed: bool)
-> ParsedItemsAndViewItems {
let mut attrs = first_item_attrs;
attrs.push_all(&self.parse_outer_attributes()[]);
// First, parse view items.
let mut view_items : Vec<ast::ViewItem> = Vec::new();
let mut items = Vec::new();
// I think this code would probably read better as a single
// loop with a mutable three-state-variable (for extern crates,
// view items, and regular items) ... except that because
// of macros, I'd like to delay that entire check until later.
loop {
match self.parse_item_or_view_item(attrs, macros_allowed) {
IoviNone(attrs) => {
return ParsedItemsAndViewItems {
attrs_remaining: attrs,
view_items: view_items,
items: items,
foreign_items: Vec::new()
}
}
IoviViewItem(view_item) => {
match view_item.node {
ViewItemUse(..) => {
// `extern crate` must precede `use`.
extern_mod_allowed = false;
}
ViewItemExternCrate(..) if !extern_mod_allowed => {
self.span_err(view_item.span,
"\"extern crate\" declarations are \
not allowed here");
}
ViewItemExternCrate(..) => {}
}
view_items.push(view_item);
}
IoviItem(item) => {
items.push(item);
attrs = self.parse_outer_attributes();
break;
}
IoviForeignItem(_) => {
panic!();
}
}
attrs = self.parse_outer_attributes();
}
// Next, parse items.
loop {
match self.parse_item_or_view_item(attrs, macros_allowed) {
IoviNone(returned_attrs) => {
attrs = returned_attrs;
break
}
IoviViewItem(view_item) => {
attrs = self.parse_outer_attributes();
self.span_err(view_item.span,
"`use` and `extern crate` declarations must precede items");
}
IoviItem(item) => {
attrs = self.parse_outer_attributes();
items.push(item)
}
IoviForeignItem(_) => {
panic!();
}
}
}
ParsedItemsAndViewItems {
attrs_remaining: attrs,
view_items: view_items,
items: items,
foreign_items: Vec::new()
}
} }
/// Parses a sequence of foreign items. Stops when it finds program /// Parses a sequence of foreign items. Stops when it finds program
/// text that can't be parsed as an item /// text that can't be parsed as an item
fn parse_foreign_items(&mut self, first_item_attrs: Vec<Attribute> , fn parse_foreign_items(&mut self, first_item_attrs: Vec<Attribute>)
macros_allowed: bool) -> Vec<P<ForeignItem>> {
-> ParsedItemsAndViewItems {
let mut attrs = first_item_attrs; let mut attrs = first_item_attrs;
attrs.push_all(&self.parse_outer_attributes()[]); attrs.push_all(&self.parse_outer_attributes()[]);
let mut foreign_items = Vec::new(); let mut foreign_items = Vec::new();
loop { loop {
match self.parse_foreign_item(attrs, macros_allowed) { match self.parse_foreign_item(attrs) {
IoviNone(returned_attrs) => { Ok(foreign_item) => {
foreign_items.push(foreign_item);
}
Err(returned_attrs) => {
if self.check(&token::CloseDelim(token::Brace)) { if self.check(&token::CloseDelim(token::Brace)) {
attrs = returned_attrs; attrs = returned_attrs;
break break
} }
self.unexpected(); self.unexpected();
},
IoviViewItem(view_item) => {
// I think this can't occur:
self.span_err(view_item.span,
"`use` and `extern crate` declarations must precede items");
}
IoviItem(item) => {
// FIXME #5668: this will occur for a macro invocation:
self.span_fatal(item.span, "macros cannot expand to foreign items");
}
IoviForeignItem(foreign_item) => {
foreign_items.push(foreign_item);
} }
} }
attrs = self.parse_outer_attributes(); attrs = self.parse_outer_attributes();
} }
ParsedItemsAndViewItems { if !attrs.is_empty() {
attrs_remaining: attrs, let last_span = self.last_span;
view_items: Vec::new(), self.span_err(last_span,
items: Vec::new(), Parser::expected_item_err(&attrs[]));
foreign_items: foreign_items
} }
foreign_items
} }
/// Parses a source module as a crate. This is the main /// Parses a source module as a crate. This is the main