Replace extern mod with extern crate

This patch adds a new keyword `crate` which is intended to replace mod
in the context of `extern mod` as part of the issue #9880. The patch
doesn't replace all `extern mod` cases since it is necessary to first
push a new snapshot 0.

The implementation could've been less invasive than this. However I
preferred to take this chance to split the `parse_item_foreign_mod`
method and pull the `extern crate` part out of there, hence the new
method `parse_item_foreign_crate`.
This commit is contained in:
Flavio Percoco 2014-02-02 23:52:06 +01:00
parent 968633b60a
commit 9a6d92c1d7
5 changed files with 157 additions and 112 deletions

View File

@ -866,7 +866,10 @@ impl Parser {
*/
let opt_abis = self.parse_opt_abis();
let opt_abis = if self.eat_keyword(keywords::Extern) {
self.parse_opt_abis()
} else { None };
let abis = opt_abis.unwrap_or(AbiSet::Rust());
let purity = self.parse_unsafety();
self.expect_keyword(keywords::Fn);
@ -4308,91 +4311,78 @@ impl Parser {
}
}
// parse extern foo; or extern mod foo { ... } or extern { ... }
/// Parse extern crate links
///
/// # Example
///
/// extern crate extra;
/// extern crate foo = "bar";
fn parse_item_extern_crate(&mut self,
lo: BytePos,
visibility: Visibility,
attrs: ~[Attribute])
-> ItemOrViewItem {
let (maybe_path, ident) = match self.token {
token::IDENT(..) => {
let the_ident = self.parse_ident();
self.expect_one_of(&[], &[token::EQ, token::SEMI]);
let path = if self.token == token::EQ {
self.bump();
Some(self.parse_str())
} else {None};
self.expect(&token::SEMI);
(path, the_ident)
}
_ => {
let token_str = self.this_token_to_str();
self.span_fatal(self.span,
format!("expected extern crate name but found `{}`",
token_str));
}
};
IoviViewItem(ast::ViewItem {
node: ViewItemExternMod(ident, maybe_path, ast::DUMMY_NODE_ID),
attrs: attrs,
vis: visibility,
span: mk_sp(lo, self.last_span.hi)
})
}
/// Parse `extern` for foreign ABIs
/// modules.
///
/// `extern` is expected to have been
/// consumed before calling this method
///
/// # Examples:
///
/// extern "C" {}
/// extern {}
fn parse_item_foreign_mod(&mut self,
lo: BytePos,
opt_abis: Option<AbiSet>,
visibility: Visibility,
attrs: ~[Attribute],
items_allowed: bool)
attrs: ~[Attribute])
-> ItemOrViewItem {
let mut must_be_named_mod = false;
if self.is_keyword(keywords::Mod) {
must_be_named_mod = true;
self.expect_keyword(keywords::Mod);
} else if self.token != token::LBRACE {
let token_str = self.this_token_to_str();
self.span_fatal(self.span,
format!("expected `\\{` or `mod` but found `{}`",
token_str))
}
let (named, maybe_path, ident) = match self.token {
token::IDENT(..) => {
let the_ident = self.parse_ident();
let path = if self.token == token::EQ {
self.bump();
Some(self.parse_str())
}
else { None };
(true, path, the_ident)
}
_ => {
if must_be_named_mod {
let token_str = self.this_token_to_str();
self.span_fatal(self.span,
format!("expected foreign module name but \
found `{}`",
token_str))
}
self.expect(&token::LBRACE);
(false, None,
special_idents::clownshoes_foreign_mod)
}
};
let abis = opt_abis.unwrap_or(AbiSet::C());
// extern mod foo { ... } or extern { ... }
if items_allowed && self.eat(&token::LBRACE) {
// `extern mod foo { ... }` is obsolete.
if named {
self.obsolete(self.last_span, ObsoleteNamedExternModule);
}
let (inner, next) = self.parse_inner_attrs_and_next();
let m = self.parse_foreign_mod_items(abis, next);
self.expect(&token::RBRACE);
let abis = opt_abis.unwrap_or(AbiSet::C());
let (inner, next) = self.parse_inner_attrs_and_next();
let m = self.parse_foreign_mod_items(abis, next);
self.expect(&token::RBRACE);
let item = self.mk_item(lo,
self.last_span.hi,
ident,
ItemForeignMod(m),
visibility,
maybe_append(attrs, Some(inner)));
return IoviItem(item);
}
if opt_abis.is_some() {
self.span_err(self.span, "an ABI may not be specified here");
}
if self.token == token::LPAREN {
// `extern mod foo (name = "bar"[,vers = "version"]) is obsolete,
// `extern mod foo = "bar#[version]";` should be used.
// Parse obsolete options to avoid wired parser errors
self.parse_optional_meta();
self.obsolete(self.span, ObsoleteExternModAttributesInParens);
}
// extern mod foo;
self.expect(&token::SEMI);
IoviViewItem(ast::ViewItem {
node: ViewItemExternMod(ident, maybe_path, ast::DUMMY_NODE_ID),
attrs: attrs,
vis: visibility,
span: mk_sp(lo, self.last_span.hi)
})
let item = self.mk_item(lo,
self.last_span.hi,
special_idents::clownshoes_foreign_mod,
ItemForeignMod(m),
visibility,
maybe_append(attrs, Some(inner)));
return IoviItem(item);
}
// parse type Foo = Bar;
@ -4504,10 +4494,6 @@ impl Parser {
// Parses a string as an ABI spec on an extern type or module. Consumes
// the `extern` keyword, if one is found.
fn parse_opt_abis(&mut self) -> Option<AbiSet> {
if !self.eat_keyword(keywords::Extern) {
return None
}
match self.token {
token::LIT_STR(s)
| token::LIT_STR_RAW(s, _) => {
@ -4585,7 +4571,20 @@ impl Parser {
});
}
// either a view item or an item:
if self.is_keyword(keywords::Extern) {
if self.eat_keyword(keywords::Extern) {
let next_is_mod = self.eat_keyword(keywords::Mod);
if next_is_mod || self.eat_keyword(keywords::Crate) {
// NOTE(flaper87): Uncomment this when this changes gets into stage0
//
// if next_is_mod {
// self.span_err(self.span,
// format!("`extern mod` is obsolete, use `extern crate` instead \
// to refer to external crates."))
// }
return self.parse_item_extern_crate(lo, visibility, attrs);
}
let opt_abis = self.parse_opt_abis();
if self.eat_keyword(keywords::Fn) {
@ -4600,12 +4599,15 @@ impl Parser {
visibility,
maybe_append(attrs, extra_attrs));
return IoviItem(item);
} else {
// EXTERN MODULE ITEM (IoviViewItem)
return self.parse_item_foreign_mod(lo, opt_abis, visibility, attrs,
true);
} else if self.token == token::LBRACE {
return self.parse_item_foreign_mod(lo, opt_abis, visibility, attrs);
}
let token_str = self.this_token_to_str();
self.span_fatal(self.span,
format!("expected `\\{` or `fn` but found `{}`", token_str));
}
// the rest are all guaranteed to be items:
if self.is_keyword(keywords::Static) {
// STATIC ITEM

View File

@ -462,37 +462,38 @@ declare_special_idents_and_keywords! {
(28, Loop, "loop");
(29, Match, "match");
(30, Mod, "mod");
(31, Mut, "mut");
(32, Once, "once");
(33, Priv, "priv");
(34, Pub, "pub");
(35, Ref, "ref");
(36, Return, "return");
(31, Crate, "crate");
(32, Mut, "mut");
(33, Once, "once");
(34, Priv, "priv");
(35, Pub, "pub");
(36, Ref, "ref");
(37, Return, "return");
// Static and Self are also special idents (prefill de-dupes)
(super::STATIC_KEYWORD_NAME, Static, "static");
(super::SELF_KEYWORD_NAME, Self, "self");
(37, Struct, "struct");
(38, Super, "super");
(39, True, "true");
(40, Trait, "trait");
(41, Type, "type");
(42, Unsafe, "unsafe");
(43, Use, "use");
(44, While, "while");
(45, Continue, "continue");
(46, Proc, "proc");
(47, Box, "box");
(38, Struct, "struct");
(39, Super, "super");
(40, True, "true");
(41, Trait, "trait");
(42, Type, "type");
(43, Unsafe, "unsafe");
(44, Use, "use");
(45, While, "while");
(46, Continue, "continue");
(47, Proc, "proc");
(48, Box, "box");
'reserved:
(48, Alignof, "alignof");
(49, Be, "be");
(50, Offsetof, "offsetof");
(51, Pure, "pure");
(52, Sizeof, "sizeof");
(53, Typeof, "typeof");
(54, Unsized, "unsized");
(55, Yield, "yield");
(56, Do, "do");
(49, Alignof, "alignof");
(50, Be, "be");
(51, Offsetof, "offsetof");
(52, Pure, "pure");
(53, Sizeof, "sizeof");
(54, Typeof, "typeof");
(55, Unsized, "unsized");
(56, Yield, "yield");
(57, Do, "do");
}
}

View File

@ -0,0 +1,14 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Verifies that the expected token errors for `extern crate` are
// raised
extern "C" mod foo; //~ERROR expected `{` or `fn` but found `mod`

View File

@ -0,0 +1,14 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Verifies that the expected token errors for `extern crate` are
// raised
extern crate foo {} //~ERROR expected one of `=`, `;` but found `{`

View File

@ -0,0 +1,14 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
extern crate extra;
extern mod mystd = "std";
pub fn main() {}