// except according to those terms.
pub use self::PathParsingMode::*;
-use self::ItemOrViewItem::*;
use abi;
use ast::{AssociatedType, BareFnTy};
use ast::{Ident, Inherited, ImplItem, Item, Item_, ItemStatic};
use ast::{ItemEnum, ItemFn, ItemForeignMod, ItemImpl, ItemConst};
use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy};
+use ast::{ItemExternCrate, ItemUse};
use ast::{LifetimeDef, Lit, Lit_};
use ast::{LitBool, LitChar, LitByte, LitBinary};
use ast::{LitStr, LitInt, Local, LocalLet};
use ast::{TyRptr, TyTup, TyU32, TyVec, UnUniq};
use ast::{TypeImplItem, TypeTraitItem, Typedef, UnboxedClosureKind};
use ast::{UnnamedField, UnsafeBlock};
-use ast::{ViewItem, ViewItem_, ViewItemExternCrate, ViewItemUse};
use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
use ast::{Visibility, WhereClause};
use ast;
Modified,
}
-enum ItemOrViewItem {
- /// Indicates a failure to parse any kind of item. The attributes are
- /// returned.
- IoviNone(Vec<Attribute>),
- IoviItem(P<Item>),
- IoviForeignItem(P<ForeignItem>),
- IoviViewItem(ViewItem)
-}
+/// 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
}
}
);
- (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) => (
{
let found = match ($p).token {
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 */
pub struct Parser<'a> {
let body = self.parse_expr();
let fakeblock = P(ast::Block {
id: ast::DUMMY_NODE_ID,
- view_items: Vec::new(),
- stmts: Vec::new(),
+ stmts: vec![],
span: body.span,
expr: Some(body),
rules: DefaultBlock,
} else {
let found_attrs = !item_attrs.is_empty();
let item_err = Parser::expected_item_err(&item_attrs[]);
- match self.parse_item_or_view_item(item_attrs, false) {
- IoviItem(i) => {
+ match self.parse_item_(item_attrs, false) {
+ Ok(i) => {
let hi = i.span.hi;
let decl = P(spanned(lo, hi, DeclItem(i)));
P(spanned(lo, hi, StmtDecl(decl, ast::DUMMY_NODE_ID)))
}
- IoviViewItem(vi) => {
- 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(_) => {
+ Err(_) => {
if found_attrs {
let last_span = self.last_span;
self.span_err(last_span, item_err);
(inner, self.parse_block_tail_(lo, DefaultBlock, next))
}
- /// Precondition: already parsed the '{' or '#{'
- /// I guess that also means "already parsed the 'impure'" if
- /// necessary, and this should take a qualifier.
- /// Some blocks start with "#{"...
+ /// Precondition: already parsed the '{'.
fn parse_block_tail(&mut self, lo: BytePos, s: BlockCheckMode) -> P<Block> {
self.parse_block_tail_(lo, s, Vec::new())
}
/// 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> {
- let mut stmts = Vec::new();
+ first_item_attrs: Vec<Attribute>) -> P<Block> {
+ let mut stmts = vec![];
let mut expr = None;
-
- // 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;
+ 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
let hi = self.span.hi;
self.bump();
P(ast::Block {
- view_items: view_items,
stmts: stmts,
expr: expr,
id: ast::DUMMY_NODE_ID,
first_item_attrs: Vec<Attribute>,
inner_lo: BytePos)
-> Mod {
- // parse all of the items up to closing or an attribute.
- // view items are legal here.
- let ParsedItemsAndViewItems {
- attrs_remaining,
- view_items,
- items: starting_items,
- ..
- } = self.parse_items_and_view_items(first_item_attrs, true, true);
- let mut items: Vec<P<Item>> = starting_items;
- let attrs_remaining_len = attrs_remaining.len();
+ // Parse all of the items up to closing or an attribute.
+
+ let mut attrs = first_item_attrs;
+ attrs.push_all(&self.parse_outer_attributes()[]);
+ 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)
+ }
+ }
+ }
// don't think this other loop is even necessary....
- let mut first = true;
while self.token != term {
- let mut attrs = self.parse_outer_attributes();
- if first {
- let mut tmp = attrs_remaining.clone();
- tmp.push_all(&attrs[]);
- attrs = tmp;
- first = false;
- }
- 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 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(_) => {
let token_str = self.this_token_to_string();
self.fatal(&format!("expected item, found `{}`",
token_str)[])
}
}
- if first && attrs_remaining_len > 0u {
+ 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_remaining[]));
+ Parser::expected_item_err(&attrs[]));
}
ast::Mod {
inner: mk_sp(inner_lo, self.span.lo),
- view_items: view_items,
items: items
}
}
/// parse_foreign_items.
fn parse_foreign_mod_items(&mut self,
abi: abi::Abi,
- first_item_attrs: Vec<Attribute> )
+ first_item_attrs: Vec<Attribute>)
-> ForeignMod {
- let ParsedItemsAndViewItems {
- 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[]));
- }
+ let foreign_items = self.parse_foreign_items(first_item_attrs);
assert!(self.token == token::CloseDelim(token::Brace));
ast::ForeignMod {
abi: abi,
- view_items: view_items,
items: foreign_items
}
}
fn parse_item_extern_crate(&mut self,
lo: BytePos,
visibility: Visibility,
- attrs: Vec<Attribute> )
- -> ItemOrViewItem {
+ attrs: Vec<Attribute>)
+ -> P<Item> {
let span = self.span;
let (maybe_path, ident) = match self.token {
}
};
- IoviViewItem(ast::ViewItem {
- node: ViewItemExternCrate(ident, maybe_path, ast::DUMMY_NODE_ID),
- attrs: attrs,
- vis: visibility,
- span: mk_sp(lo, self.last_span.hi)
- })
+ let last_span = self.last_span;
+ self.mk_item(lo,
+ last_span.hi,
+ ident,
+ ItemExternCrate(maybe_path),
+ visibility,
+ attrs)
}
/// Parse `extern` for foreign ABIs
lo: BytePos,
opt_abi: Option<abi::Abi>,
visibility: Visibility,
- attrs: Vec<Attribute> )
- -> ItemOrViewItem {
+ attrs: Vec<Attribute>)
+ -> P<Item> {
self.expect(&token::OpenDelim(token::Brace));
self.expect(&token::CloseDelim(token::Brace));
let last_span = self.last_span;
- let item = self.mk_item(lo,
- last_span.hi,
- special_idents::invalid,
- ItemForeignMod(m),
- visibility,
- maybe_append(attrs, Some(inner)));
- return IoviItem(item);
+ self.mk_item(lo,
+ last_span.hi,
+ special_idents::invalid,
+ ItemForeignMod(m),
+ visibility,
+ maybe_append(attrs, Some(inner)))
}
/// Parse type Foo = Bar;
}
}
- /// Parse one of the items or view items allowed by the
- /// flags; on failure, return IoviNone.
+ /// Parse one of the items allowed by the flags; on failure,
+ /// return `Err(remaining_attrs)`.
/// NB: this function no longer parses the items inside an
/// extern crate.
- fn parse_item_or_view_item(&mut self,
- attrs: Vec<Attribute> ,
- macros_allowed: bool)
- -> ItemOrViewItem {
+ fn parse_item_(&mut self, attrs: Vec<Attribute>,
+ macros_allowed: bool) -> MaybeItem {
let nt_item = match self.token {
token::Interpolated(token::NtItem(ref item)) => {
Some((**item).clone())
let mut attrs = attrs;
mem::swap(&mut item.attrs, &mut attrs);
item.attrs.extend(attrs.into_iter());
- return IoviItem(P(item));
+ return Ok(P(item));
}
None => {}
}
let visibility = self.parse_visibility();
- // must be a view item:
if self.eat_keyword(keywords::Use) {
- // USE ITEM (IoviViewItem)
- let view_item = self.parse_use();
+ // USE ITEM
+ let item_ = ItemUse(self.parse_view_path());
self.expect(&token::Semi);
- return IoviViewItem(ast::ViewItem {
- node: view_item,
- attrs: attrs,
- vis: visibility,
- span: mk_sp(lo, self.last_span.hi)
- });
+
+ let last_span = self.last_span;
+ let item = self.mk_item(lo,
+ 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::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();
item_,
visibility,
maybe_append(attrs, extra_attrs));
- return IoviItem(item);
+ return Ok(item);
} 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;
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) {
// STATIC ITEM
self.bump();
item_,
visibility,
maybe_append(attrs, extra_attrs));
- return IoviItem(item);
+ return Ok(item);
}
if self.token.is_keyword(keywords::Const) {
// CONST ITEM
item_,
visibility,
maybe_append(attrs, extra_attrs));
- return IoviItem(item);
+ return Ok(item);
}
if self.token.is_keyword(keywords::Unsafe) &&
self.look_ahead(1u, |t| t.is_keyword(keywords::Trait))
item_,
visibility,
maybe_append(attrs, extra_attrs));
- return IoviItem(item);
+ return Ok(item);
}
if self.token.is_keyword(keywords::Unsafe) &&
self.look_ahead(1u, |t| t.is_keyword(keywords::Impl))
item_,
visibility,
maybe_append(attrs, extra_attrs));
- return IoviItem(item);
+ return Ok(item);
}
if self.token.is_keyword(keywords::Fn) {
// FUNCTION ITEM
item_,
visibility,
maybe_append(attrs, extra_attrs));
- return IoviItem(item);
+ return Ok(item);
}
if self.token.is_keyword(keywords::Unsafe)
&& self.look_ahead(1u, |t| *t != token::OpenDelim(token::Brace)) {
item_,
visibility,
maybe_append(attrs, extra_attrs));
- return IoviItem(item);
+ return Ok(item);
}
if self.eat_keyword(keywords::Mod) {
// MODULE ITEM
item_,
visibility,
maybe_append(attrs, extra_attrs));
- return IoviItem(item);
+ return Ok(item);
}
if self.eat_keyword(keywords::Type) {
// TYPE ITEM
item_,
visibility,
maybe_append(attrs, extra_attrs));
- return IoviItem(item);
+ return Ok(item);
}
if self.eat_keyword(keywords::Enum) {
// ENUM ITEM
item_,
visibility,
maybe_append(attrs, extra_attrs));
- return IoviItem(item);
+ return Ok(item);
}
if self.eat_keyword(keywords::Trait) {
// TRAIT ITEM
item_,
visibility,
maybe_append(attrs, extra_attrs));
- return IoviItem(item);
+ return Ok(item);
}
if self.eat_keyword(keywords::Impl) {
// IMPL ITEM
item_,
visibility,
maybe_append(attrs, extra_attrs));
- return IoviItem(item);
+ return Ok(item);
}
if self.eat_keyword(keywords::Struct) {
// STRUCT ITEM
item_,
visibility,
maybe_append(attrs, extra_attrs));
- return IoviItem(item);
+ return Ok(item);
}
self.parse_macro_use_or_failure(attrs,macros_allowed,lo,visibility)
}
- /// Parse a foreign item; on failure, return IoviNone.
- fn parse_foreign_item(&mut self,
- attrs: Vec<Attribute> ,
- macros_allowed: bool)
- -> ItemOrViewItem {
- maybe_whole!(iovi self, NtItem);
+ /// Parse a foreign item; on failure, return `Err(remaining_attrs)`.
+ fn parse_foreign_item(&mut self, attrs: Vec<Attribute>)
+ -> Result<P<ForeignItem>, Vec<Attribute>> {
let lo = self.span.lo;
let visibility = self.parse_visibility();
if self.token.is_keyword(keywords::Static) {
// FOREIGN STATIC ITEM
- let item = self.parse_item_foreign_static(visibility, attrs);
- return IoviForeignItem(item);
+ return Ok(self.parse_item_foreign_static(visibility, attrs));
}
if self.token.is_keyword(keywords::Fn) || self.token.is_keyword(keywords::Unsafe) {
// FOREIGN FUNCTION ITEM
- let item = self.parse_item_foreign_fn(visibility, attrs);
- return IoviForeignItem(item);
+ return Ok(self.parse_item_foreign_fn(visibility, attrs));
}
- 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.
macros_allowed: bool,
lo: BytePos,
visibility: Visibility
- ) -> ItemOrViewItem {
+ ) -> MaybeItem {
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())
item_,
visibility,
attrs);
- return IoviItem(item);
+ return Ok(item);
}
// FAILURE TO PARSE ITEM
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(&mut self, attrs: Vec<Attribute>) -> Option<P<Item>> {
- match self.parse_item_or_view_item(attrs, true) {
- IoviNone(_) => None,
- IoviViewItem(_) =>
- self.fatal("view items are not allowed here"),
- IoviForeignItem(_) =>
- self.fatal("foreign items are not allowed here"),
- IoviItem(item) => Some(item)
- }
+ self.parse_item_(attrs, true).ok()
}
- /// 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
/// | MOD? non_global_path MOD_SEP LBRACE RBRACE
/// | MOD? non_global_path MOD_SEP LBRACE ident_seq RBRACE
global: false,
segments: Vec::new()
};
- return P(spanned(lo, self.span.hi,
- ViewPathList(path, idents, ast::DUMMY_NODE_ID)));
+ return P(spanned(lo, self.span.hi, ViewPathList(path, idents)));
}
let first_ident = self.parse_ident();
}
}).collect()
};
- return P(spanned(lo, self.span.hi,
- ViewPathList(path, idents, ast::DUMMY_NODE_ID)));
+ return P(spanned(lo, self.span.hi, ViewPathList(path, idents)));
}
// foo::bar::*
}
}).collect()
};
- return P(spanned(lo, self.span.hi,
- ViewPathGlob(path, ast::DUMMY_NODE_ID)));
+ return P(spanned(lo, self.span.hi, ViewPathGlob(path)));
}
_ => break
if self.eat_keyword(keywords::As) {
rename_to = self.parse_ident()
}
- P(spanned(lo,
- 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()
- }
+ 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> ,
- macros_allowed: bool)
- -> ParsedItemsAndViewItems {
+ 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, macros_allowed) {
- IoviNone(returned_attrs) => {
+ 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();
- },
- 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();
}
- ParsedItemsAndViewItems {
- attrs_remaining: attrs,
- view_items: Vec::new(),
- items: Vec::new(),
- foreign_items: foreign_items
+ 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