Skip to content

Commit 9a6d92c

Browse files
committed
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`.
1 parent 968633b commit 9a6d92c

File tree

5 files changed

+150
-105
lines changed

5 files changed

+150
-105
lines changed

src/libsyntax/parse/parser.rs

Lines changed: 81 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -866,7 +866,10 @@ impl Parser {
866866
867867
*/
868868

869-
let opt_abis = self.parse_opt_abis();
869+
let opt_abis = if self.eat_keyword(keywords::Extern) {
870+
self.parse_opt_abis()
871+
} else { None };
872+
870873
let abis = opt_abis.unwrap_or(AbiSet::Rust());
871874
let purity = self.parse_unsafety();
872875
self.expect_keyword(keywords::Fn);
@@ -4308,91 +4311,78 @@ impl Parser {
43084311
}
43094312
}
43104313

4311-
// parse extern foo; or extern mod foo { ... } or extern { ... }
4312-
fn parse_item_foreign_mod(&mut self,
4313-
lo: BytePos,
4314-
opt_abis: Option<AbiSet>,
4315-
visibility: Visibility,
4316-
attrs: ~[Attribute],
4317-
items_allowed: bool)
4318-
-> ItemOrViewItem {
4319-
let mut must_be_named_mod = false;
4320-
if self.is_keyword(keywords::Mod) {
4321-
must_be_named_mod = true;
4322-
self.expect_keyword(keywords::Mod);
4323-
} else if self.token != token::LBRACE {
4324-
let token_str = self.this_token_to_str();
4325-
self.span_fatal(self.span,
4326-
format!("expected `\\{` or `mod` but found `{}`",
4327-
token_str))
4328-
}
4314+
/// Parse extern crate links
4315+
///
4316+
/// # Example
4317+
///
4318+
/// extern crate extra;
4319+
/// extern crate foo = "bar";
4320+
fn parse_item_extern_crate(&mut self,
4321+
lo: BytePos,
4322+
visibility: Visibility,
4323+
attrs: ~[Attribute])
4324+
-> ItemOrViewItem {
43294325

4330-
let (named, maybe_path, ident) = match self.token {
4326+
let (maybe_path, ident) = match self.token {
43314327
token::IDENT(..) => {
43324328
let the_ident = self.parse_ident();
4329+
self.expect_one_of(&[], &[token::EQ, token::SEMI]);
43334330
let path = if self.token == token::EQ {
43344331
self.bump();
43354332
Some(self.parse_str())
4336-
}
4337-
else { None };
4338-
(true, path, the_ident)
4333+
} else {None};
4334+
4335+
self.expect(&token::SEMI);
4336+
(path, the_ident)
43394337
}
43404338
_ => {
4341-
if must_be_named_mod {
4342-
let token_str = self.this_token_to_str();
4343-
self.span_fatal(self.span,
4344-
format!("expected foreign module name but \
4345-
found `{}`",
4346-
token_str))
4347-
}
4348-
4349-
(false, None,
4350-
special_idents::clownshoes_foreign_mod)
4339+
let token_str = self.this_token_to_str();
4340+
self.span_fatal(self.span,
4341+
format!("expected extern crate name but found `{}`",
4342+
token_str));
43514343
}
43524344
};
43534345

4354-
// extern mod foo { ... } or extern { ... }
4355-
if items_allowed && self.eat(&token::LBRACE) {
4356-
// `extern mod foo { ... }` is obsolete.
4357-
if named {
4358-
self.obsolete(self.last_span, ObsoleteNamedExternModule);
4359-
}
4360-
4361-
let abis = opt_abis.unwrap_or(AbiSet::C());
4346+
IoviViewItem(ast::ViewItem {
4347+
node: ViewItemExternMod(ident, maybe_path, ast::DUMMY_NODE_ID),
4348+
attrs: attrs,
4349+
vis: visibility,
4350+
span: mk_sp(lo, self.last_span.hi)
4351+
})
4352+
}
43624353

4363-
let (inner, next) = self.parse_inner_attrs_and_next();
4364-
let m = self.parse_foreign_mod_items(abis, next);
4365-
self.expect(&token::RBRACE);
4354+
/// Parse `extern` for foreign ABIs
4355+
/// modules.
4356+
///
4357+
/// `extern` is expected to have been
4358+
/// consumed before calling this method
4359+
///
4360+
/// # Examples:
4361+
///
4362+
/// extern "C" {}
4363+
/// extern {}
4364+
fn parse_item_foreign_mod(&mut self,
4365+
lo: BytePos,
4366+
opt_abis: Option<AbiSet>,
4367+
visibility: Visibility,
4368+
attrs: ~[Attribute])
4369+
-> ItemOrViewItem {
43664370

4367-
let item = self.mk_item(lo,
4368-
self.last_span.hi,
4369-
ident,
4370-
ItemForeignMod(m),
4371-
visibility,
4372-
maybe_append(attrs, Some(inner)));
4373-
return IoviItem(item);
4374-
}
4371+
self.expect(&token::LBRACE);
43754372

4376-
if opt_abis.is_some() {
4377-
self.span_err(self.span, "an ABI may not be specified here");
4378-
}
4373+
let abis = opt_abis.unwrap_or(AbiSet::C());
43794374

4375+
let (inner, next) = self.parse_inner_attrs_and_next();
4376+
let m = self.parse_foreign_mod_items(abis, next);
4377+
self.expect(&token::RBRACE);
43804378

4381-
if self.token == token::LPAREN {
4382-
// `extern mod foo (name = "bar"[,vers = "version"]) is obsolete,
4383-
// `extern mod foo = "bar#[version]";` should be used.
4384-
// Parse obsolete options to avoid wired parser errors
4385-
self.parse_optional_meta();
4386-
self.obsolete(self.span, ObsoleteExternModAttributesInParens);
4387-
}
4388-
// extern mod foo;
4389-
self.expect(&token::SEMI);
4390-
IoviViewItem(ast::ViewItem {
4391-
node: ViewItemExternMod(ident, maybe_path, ast::DUMMY_NODE_ID),
4392-
attrs: attrs,
4393-
vis: visibility,
4394-
span: mk_sp(lo, self.last_span.hi)
4395-
})
4379+
let item = self.mk_item(lo,
4380+
self.last_span.hi,
4381+
special_idents::clownshoes_foreign_mod,
4382+
ItemForeignMod(m),
4383+
visibility,
4384+
maybe_append(attrs, Some(inner)));
4385+
return IoviItem(item);
43964386
}
43974387

43984388
// parse type Foo = Bar;
@@ -4504,10 +4494,6 @@ impl Parser {
45044494
// Parses a string as an ABI spec on an extern type or module. Consumes
45054495
// the `extern` keyword, if one is found.
45064496
fn parse_opt_abis(&mut self) -> Option<AbiSet> {
4507-
if !self.eat_keyword(keywords::Extern) {
4508-
return None
4509-
}
4510-
45114497
match self.token {
45124498
token::LIT_STR(s)
45134499
| token::LIT_STR_RAW(s, _) => {
@@ -4585,7 +4571,20 @@ impl Parser {
45854571
});
45864572
}
45874573
// either a view item or an item:
4588-
if self.is_keyword(keywords::Extern) {
4574+
if self.eat_keyword(keywords::Extern) {
4575+
let next_is_mod = self.eat_keyword(keywords::Mod);
4576+
4577+
if next_is_mod || self.eat_keyword(keywords::Crate) {
4578+
// NOTE(flaper87): Uncomment this when this changes gets into stage0
4579+
//
4580+
// if next_is_mod {
4581+
// self.span_err(self.span,
4582+
// format!("`extern mod` is obsolete, use `extern crate` instead \
4583+
// to refer to external crates."))
4584+
// }
4585+
return self.parse_item_extern_crate(lo, visibility, attrs);
4586+
}
4587+
45894588
let opt_abis = self.parse_opt_abis();
45904589

45914590
if self.eat_keyword(keywords::Fn) {
@@ -4600,12 +4599,15 @@ impl Parser {
46004599
visibility,
46014600
maybe_append(attrs, extra_attrs));
46024601
return IoviItem(item);
4603-
} else {
4604-
// EXTERN MODULE ITEM (IoviViewItem)
4605-
return self.parse_item_foreign_mod(lo, opt_abis, visibility, attrs,
4606-
true);
4602+
} else if self.token == token::LBRACE {
4603+
return self.parse_item_foreign_mod(lo, opt_abis, visibility, attrs);
46074604
}
4605+
4606+
let token_str = self.this_token_to_str();
4607+
self.span_fatal(self.span,
4608+
format!("expected `\\{` or `fn` but found `{}`", token_str));
46084609
}
4610+
46094611
// the rest are all guaranteed to be items:
46104612
if self.is_keyword(keywords::Static) {
46114613
// STATIC ITEM

src/libsyntax/parse/token.rs

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -462,37 +462,38 @@ declare_special_idents_and_keywords! {
462462
(28, Loop, "loop");
463463
(29, Match, "match");
464464
(30, Mod, "mod");
465-
(31, Mut, "mut");
466-
(32, Once, "once");
467-
(33, Priv, "priv");
468-
(34, Pub, "pub");
469-
(35, Ref, "ref");
470-
(36, Return, "return");
465+
(31, Crate, "crate");
466+
(32, Mut, "mut");
467+
(33, Once, "once");
468+
(34, Priv, "priv");
469+
(35, Pub, "pub");
470+
(36, Ref, "ref");
471+
(37, Return, "return");
471472
// Static and Self are also special idents (prefill de-dupes)
472473
(super::STATIC_KEYWORD_NAME, Static, "static");
473474
(super::SELF_KEYWORD_NAME, Self, "self");
474-
(37, Struct, "struct");
475-
(38, Super, "super");
476-
(39, True, "true");
477-
(40, Trait, "trait");
478-
(41, Type, "type");
479-
(42, Unsafe, "unsafe");
480-
(43, Use, "use");
481-
(44, While, "while");
482-
(45, Continue, "continue");
483-
(46, Proc, "proc");
484-
(47, Box, "box");
475+
(38, Struct, "struct");
476+
(39, Super, "super");
477+
(40, True, "true");
478+
(41, Trait, "trait");
479+
(42, Type, "type");
480+
(43, Unsafe, "unsafe");
481+
(44, Use, "use");
482+
(45, While, "while");
483+
(46, Continue, "continue");
484+
(47, Proc, "proc");
485+
(48, Box, "box");
485486

486487
'reserved:
487-
(48, Alignof, "alignof");
488-
(49, Be, "be");
489-
(50, Offsetof, "offsetof");
490-
(51, Pure, "pure");
491-
(52, Sizeof, "sizeof");
492-
(53, Typeof, "typeof");
493-
(54, Unsized, "unsized");
494-
(55, Yield, "yield");
495-
(56, Do, "do");
488+
(49, Alignof, "alignof");
489+
(50, Be, "be");
490+
(51, Offsetof, "offsetof");
491+
(52, Pure, "pure");
492+
(53, Sizeof, "sizeof");
493+
(54, Typeof, "typeof");
494+
(55, Unsized, "unsized");
495+
(56, Yield, "yield");
496+
(57, Do, "do");
496497
}
497498
}
498499

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Verifies that the expected token errors for `extern crate` are
12+
// raised
13+
14+
extern "C" mod foo; //~ERROR expected `{` or `fn` but found `mod`
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Verifies that the expected token errors for `extern crate` are
12+
// raised
13+
14+
extern crate foo {} //~ERROR expected one of `=`, `;` but found `{`
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
extern crate extra;
12+
extern mod mystd = "std";
13+
14+
pub fn main() {}

0 commit comments

Comments
 (0)