Skip to content

Commit 0631b46

Browse files
committed
rollup merge of rust-lang#19430: pczarn/interp_tt-cleanup
Conflicts: src/libsyntax/parse/parser.rs
2 parents 771fe90 + d85c017 commit 0631b46

File tree

12 files changed

+170
-103
lines changed

12 files changed

+170
-103
lines changed

src/doc/reference.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -690,10 +690,9 @@ balanced, but they are otherwise not special.
690690

691691
In the matcher, `$` _name_ `:` _designator_ matches the nonterminal in the Rust
692692
syntax named by _designator_. Valid designators are `item`, `block`, `stmt`,
693-
`pat`, `expr`, `ty` (type), `ident`, `path`, `matchers` (lhs of the `=>` in
694-
macro rules), `tt` (rhs of the `=>` in macro rules). In the transcriber, the
695-
designator is already known, and so only the name of a matched nonterminal
696-
comes after the dollar sign.
693+
`pat`, `expr`, `ty` (type), `ident`, `path`, `tt` (either side of the `=>`
694+
in macro rules). In the transcriber, the designator is already known, and so
695+
only the name of a matched nonterminal comes after the dollar sign.
697696

698697
In both the matcher and transcriber, the Kleene star-like operator indicates
699698
repetition. The Kleene star operator consists of `$` and parens, optionally

src/libstd/io/mod.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1780,9 +1780,11 @@ pub struct UnstableFileStat {
17801780
pub gen: u64,
17811781
}
17821782

1783+
1784+
// NOTE(stage0): change this one last #[doc=..] to /// after the next snapshot
17831785
bitflags! {
1784-
#[doc = "A set of permissions for a file or directory is represented"]
1785-
#[doc = "by a set of flags which are or'd together."]
1786+
#[doc = "A set of permissions for a file or directory is represented by a set of"]
1787+
/// flags which are or'd together.
17861788
flags FilePermission: u32 {
17871789
const USER_READ = 0o400,
17881790
const USER_WRITE = 0o200,
@@ -1798,20 +1800,20 @@ bitflags! {
17981800
const GROUP_RWX = GROUP_READ.bits | GROUP_WRITE.bits | GROUP_EXECUTE.bits,
17991801
const OTHER_RWX = OTHER_READ.bits | OTHER_WRITE.bits | OTHER_EXECUTE.bits,
18001802

1801-
#[doc = "Permissions for user owned files, equivalent to 0644 on"]
1802-
#[doc = "unix-like systems."]
1803+
/// Permissions for user owned files, equivalent to 0644 on unix-like
1804+
/// systems.
18031805
const USER_FILE = USER_READ.bits | USER_WRITE.bits | GROUP_READ.bits | OTHER_READ.bits,
18041806

1805-
#[doc = "Permissions for user owned directories, equivalent to 0755 on"]
1806-
#[doc = "unix-like systems."]
1807+
/// Permissions for user owned directories, equivalent to 0755 on
1808+
/// unix-like systems.
18071809
const USER_DIR = USER_RWX.bits | GROUP_READ.bits | GROUP_EXECUTE.bits |
18081810
OTHER_READ.bits | OTHER_EXECUTE.bits,
18091811

1810-
#[doc = "Permissions for user owned executables, equivalent to 0755"]
1811-
#[doc = "on unix-like systems."]
1812+
/// Permissions for user owned executables, equivalent to 0755
1813+
/// on unix-like systems.
18121814
const USER_EXEC = USER_DIR.bits,
18131815

1814-
#[doc = "All possible permissions enabled."]
1816+
/// All possible permissions enabled.
18151817
const ALL_PERMISSIONS = USER_RWX.bits | GROUP_RWX.bits | OTHER_RWX.bits,
18161818
}
18171819
}

src/libsyntax/ast.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -880,7 +880,6 @@ impl TokenTree {
880880
pub fn len(&self) -> uint {
881881
match *self {
882882
TtToken(_, token::DocComment(_)) => 2,
883-
TtToken(_, token::SubstNt(..)) => 2,
884883
TtToken(_, token::SpecialVarNt(..)) => 2,
885884
TtToken(_, token::MatchNt(..)) => 3,
886885
TtDelimited(_, ref delimed) => {
@@ -918,11 +917,6 @@ impl TokenTree {
918917
}
919918
delimed.tts[index - 1].clone()
920919
}
921-
(&TtToken(sp, token::SubstNt(name, name_st)), _) => {
922-
let v = [TtToken(sp, token::Dollar),
923-
TtToken(sp, token::Ident(name, name_st))];
924-
v[index]
925-
}
926920
(&TtToken(sp, token::SpecialVarNt(var)), _) => {
927921
let v = [TtToken(sp, token::Dollar),
928922
TtToken(sp, token::Ident(token::str_to_ident(var.as_str()),

src/libsyntax/ext/tt/macro_parser.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,17 @@ pub fn parse(sess: &ParseSess,
506506
}
507507

508508
pub fn parse_nt(p: &mut Parser, name: &str) -> Nonterminal {
509+
match name {
510+
"tt" => {
511+
p.quote_depth += 1u; //but in theory, non-quoted tts might be useful
512+
let res = token::NtTT(P(p.parse_token_tree()));
513+
p.quote_depth -= 1u;
514+
return res;
515+
}
516+
_ => {}
517+
}
518+
// check at the beginning and the parser checks after each bump
519+
p.check_unknown_macro_variable();
509520
match name {
510521
"item" => match p.parse_item(Vec::new()) {
511522
Some(i) => token::NtItem(i),
@@ -529,12 +540,6 @@ pub fn parse_nt(p: &mut Parser, name: &str) -> Nonterminal {
529540
token::NtPath(box p.parse_path(LifetimeAndTypesWithoutColons))
530541
}
531542
"meta" => token::NtMeta(p.parse_meta_item()),
532-
"tt" => {
533-
p.quote_depth += 1u; //but in theory, non-quoted tts might be useful
534-
let res = token::NtTT(P(p.parse_token_tree()));
535-
p.quote_depth -= 1u;
536-
res
537-
}
538543
_ => {
539544
p.fatal(format!("unsupported builtin nonterminal parser: {}", name).index(&FullRange))
540545
}

src/libsyntax/ext/tt/macro_rules.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use ext::base::{NormalTT, TTMacroExpander};
1616
use ext::tt::macro_parser::{Success, Error, Failure};
1717
use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal};
1818
use ext::tt::macro_parser::{parse, parse_or_else};
19-
use parse::lexer::new_tt_reader;
19+
use parse::lexer::{new_tt_reader, new_tt_reader_with_doc_flag};
2020
use parse::parser::Parser;
2121
use parse::attr::ParserAttr;
2222
use parse::token::{special_idents, gensym_ident};
@@ -158,13 +158,13 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
158158
_ => cx.span_fatal(sp, "malformed macro lhs")
159159
};
160160
// `None` is because we're not interpolating
161-
let mut arg_rdr = new_tt_reader(&cx.parse_sess().span_diagnostic,
162-
None,
163-
None,
164-
arg.iter()
165-
.map(|x| (*x).clone())
166-
.collect());
167-
arg_rdr.desugar_doc_comments = true;
161+
let arg_rdr = new_tt_reader_with_doc_flag(&cx.parse_sess().span_diagnostic,
162+
None,
163+
None,
164+
arg.iter()
165+
.map(|x| (*x).clone())
166+
.collect(),
167+
true);
168168
match parse(cx.parse_sess(), cx.cfg(), arg_rdr, lhs_tt) {
169169
Success(named_matches) => {
170170
let rhs = match *rhses[i] {
@@ -183,7 +183,8 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
183183
Some(named_matches),
184184
imported_from,
185185
rhs);
186-
let p = Parser::new(cx.parse_sess(), cx.cfg(), box trncbr);
186+
let mut p = Parser::new(cx.parse_sess(), cx.cfg(), box trncbr);
187+
p.check_unknown_macro_variable();
187188
// Let the context choose how to interpret the result.
188189
// Weird, but useful for X-macros.
189190
return box ParserAnyMacro {

src/libsyntax/ext/tt/transcribe.rs

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,28 @@ pub struct TtReader<'a> {
5353
}
5454

5555
/// This can do Macro-By-Example transcription. On the other hand, if
56-
/// `src` contains no `TtSequence`s and `TtNonterminal`s, `interp` can (and
57-
/// should) be none.
56+
/// `src` contains no `TtSequence`s, `MatchNt`s or `SubstNt`s, `interp` can
57+
/// (and should) be None.
5858
pub fn new_tt_reader<'a>(sp_diag: &'a SpanHandler,
5959
interp: Option<HashMap<Ident, Rc<NamedMatch>>>,
6060
imported_from: Option<Ident>,
61-
src: Vec<ast::TokenTree> )
61+
src: Vec<ast::TokenTree>)
6262
-> TtReader<'a> {
63+
new_tt_reader_with_doc_flag(sp_diag, interp, imported_from, src, false)
64+
}
65+
66+
/// The extra `desugar_doc_comments` flag enables reading doc comments
67+
/// like any other attribute which consists of `meta` and surrounding #[ ] tokens.
68+
///
69+
/// This can do Macro-By-Example transcription. On the other hand, if
70+
/// `src` contains no `TtSequence`s, `MatchNt`s or `SubstNt`s, `interp` can
71+
/// (and should) be None.
72+
pub fn new_tt_reader_with_doc_flag<'a>(sp_diag: &'a SpanHandler,
73+
interp: Option<HashMap<Ident, Rc<NamedMatch>>>,
74+
imported_from: Option<Ident>,
75+
src: Vec<ast::TokenTree>,
76+
desugar_doc_comments: bool)
77+
-> TtReader<'a> {
6378
let mut r = TtReader {
6479
sp_diag: sp_diag,
6580
stack: vec!(TtFrame {
@@ -80,7 +95,7 @@ pub fn new_tt_reader<'a>(sp_diag: &'a SpanHandler,
8095
crate_name_next: None,
8196
repeat_idx: Vec::new(),
8297
repeat_len: Vec::new(),
83-
desugar_doc_comments: false,
98+
desugar_doc_comments: desugar_doc_comments,
8499
/* dummy values, never read: */
85100
cur_tok: token::Eof,
86101
cur_span: DUMMY_SP,
@@ -266,18 +281,15 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
266281
}
267282
// FIXME #2887: think about span stuff here
268283
TtToken(sp, SubstNt(ident, namep)) => {
284+
r.stack.last_mut().unwrap().idx += 1;
269285
match lookup_cur_matched(r, ident) {
270286
None => {
271-
r.stack.push(TtFrame {
272-
forest: TtToken(sp, SubstNt(ident, namep)),
273-
idx: 0,
274-
dotdotdoted: false,
275-
sep: None
276-
});
287+
r.cur_span = sp;
288+
r.cur_tok = SubstNt(ident, namep);
289+
return ret_val;
277290
// this can't be 0 length, just like TtDelimited
278291
}
279292
Some(cur_matched) => {
280-
r.stack.last_mut().unwrap().idx += 1;
281293
match *cur_matched {
282294
// sidestep the interpolation tricks for ident because
283295
// (a) idents can be in lots of places, so it'd be a pain

src/libsyntax/parse/lexer/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use std::rc::Rc;
2525
use std::str;
2626
use std::string::CowString;
2727

28-
pub use ext::tt::transcribe::{TtReader, new_tt_reader};
28+
pub use ext::tt::transcribe::{TtReader, new_tt_reader, new_tt_reader_with_doc_flag};
2929

3030
pub mod comments;
3131

src/libsyntax/parse/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,9 @@ pub fn tts_to_parser<'a>(sess: &'a ParseSess,
296296
tts: Vec<ast::TokenTree>,
297297
cfg: ast::CrateConfig) -> Parser<'a> {
298298
let trdr = lexer::new_tt_reader(&sess.span_diagnostic, None, None, tts);
299-
Parser::new(sess, cfg, box trdr)
299+
let mut p = Parser::new(sess, cfg, box trdr);
300+
p.check_unknown_macro_variable();
301+
p
300302
}
301303

302304
// FIXME (Issue #16472): The `with_hygiene` mod should go away after

src/libsyntax/parse/parser.rs

Lines changed: 83 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -946,6 +946,8 @@ impl<'a> Parser<'a> {
946946
self.token = next.tok;
947947
self.tokens_consumed += 1u;
948948
self.expected_tokens.clear();
949+
// check after each token
950+
self.check_unknown_macro_variable();
949951
}
950952

951953
/// Advance the parser by one token and return the bumped token.
@@ -2596,6 +2598,70 @@ impl<'a> Parser<'a> {
25962598
return e;
25972599
}
25982600

2601+
// Parse unquoted tokens after a `$` in a token tree
2602+
fn parse_unquoted(&mut self) -> TokenTree {
2603+
let mut sp = self.span;
2604+
let (name, namep) = match self.token {
2605+
token::Dollar => {
2606+
self.bump();
2607+
2608+
if self.token == token::OpenDelim(token::Paren) {
2609+
let Spanned { node: seq, span: seq_span } = self.parse_seq(
2610+
&token::OpenDelim(token::Paren),
2611+
&token::CloseDelim(token::Paren),
2612+
seq_sep_none(),
2613+
|p| p.parse_token_tree()
2614+
);
2615+
let (sep, repeat) = self.parse_sep_and_kleene_op();
2616+
let name_num = macro_parser::count_names(seq[]);
2617+
return TtSequence(mk_sp(sp.lo, seq_span.hi),
2618+
Rc::new(SequenceRepetition {
2619+
tts: seq,
2620+
separator: sep,
2621+
op: repeat,
2622+
num_captures: name_num
2623+
}));
2624+
} else if self.token.is_keyword_allow_following_colon(keywords::Crate) {
2625+
self.bump();
2626+
return TtToken(sp, SpecialVarNt(SpecialMacroVar::CrateMacroVar));
2627+
} else {
2628+
sp = mk_sp(sp.lo, self.span.hi);
2629+
let namep = match self.token { token::Ident(_, p) => p, _ => token::Plain };
2630+
let name = self.parse_ident();
2631+
(name, namep)
2632+
}
2633+
}
2634+
token::SubstNt(name, namep) => {
2635+
self.bump();
2636+
(name, namep)
2637+
}
2638+
_ => unreachable!()
2639+
};
2640+
// continue by trying to parse the `:ident` after `$name`
2641+
if self.token == token::Colon && self.look_ahead(1, |t| t.is_ident() &&
2642+
!t.is_strict_keyword() &&
2643+
!t.is_reserved_keyword()) {
2644+
self.bump();
2645+
sp = mk_sp(sp.lo, self.span.hi);
2646+
let kindp = match self.token { token::Ident(_, p) => p, _ => token::Plain };
2647+
let nt_kind = self.parse_ident();
2648+
TtToken(sp, MatchNt(name, nt_kind, namep, kindp))
2649+
} else {
2650+
TtToken(sp, SubstNt(name, namep))
2651+
}
2652+
}
2653+
2654+
pub fn check_unknown_macro_variable(&mut self) {
2655+
if self.quote_depth == 0u {
2656+
match self.token {
2657+
token::SubstNt(name, _) =>
2658+
self.fatal(format!("unknown macro variable `{}`",
2659+
token::get_ident(name))[]),
2660+
_ => {}
2661+
}
2662+
}
2663+
}
2664+
25992665
/// Parse an optional separator followed by a Kleene-style
26002666
/// repetition token (+ or *).
26012667
pub fn parse_sep_and_kleene_op(&mut self) -> (Option<token::Token>, ast::KleeneOp) {
@@ -2642,63 +2708,25 @@ impl<'a> Parser<'a> {
26422708
fn parse_non_delim_tt_tok(p: &mut Parser) -> TokenTree {
26432709
maybe_whole!(deref p, NtTT);
26442710
match p.token {
2645-
token::CloseDelim(_) => {
2646-
// This is a conservative error: only report the last unclosed delimiter. The
2647-
// previous unclosed delimiters could actually be closed! The parser just hasn't
2648-
// gotten to them yet.
2649-
match p.open_braces.last() {
2650-
None => {}
2651-
Some(&sp) => p.span_note(sp, "unclosed delimiter"),
2652-
};
2653-
let token_str = p.this_token_to_string();
2654-
p.fatal(format!("incorrect close delimiter: `{}`",
2655-
token_str).index(&FullRange))
2656-
},
2657-
/* we ought to allow different depths of unquotation */
2658-
token::Dollar if p.quote_depth > 0u => {
2659-
p.bump();
2660-
let sp = p.span;
2661-
2662-
if p.token == token::OpenDelim(token::Paren) {
2663-
let seq = p.parse_seq(
2664-
&token::OpenDelim(token::Paren),
2665-
&token::CloseDelim(token::Paren),
2666-
seq_sep_none(),
2667-
|p| p.parse_token_tree()
2668-
);
2669-
let (sep, repeat) = p.parse_sep_and_kleene_op();
2670-
let seq = match seq {
2671-
Spanned { node, .. } => node,
2711+
token::CloseDelim(_) => {
2712+
// This is a conservative error: only report the last unclosed delimiter. The
2713+
// previous unclosed delimiters could actually be closed! The parser just hasn't
2714+
// gotten to them yet.
2715+
match p.open_braces.last() {
2716+
None => {}
2717+
Some(&sp) => p.span_note(sp, "unclosed delimiter"),
26722718
};
2673-
let name_num = macro_parser::count_names(seq.index(&FullRange));
2674-
TtSequence(mk_sp(sp.lo, p.span.hi),
2675-
Rc::new(SequenceRepetition {
2676-
tts: seq,
2677-
separator: sep,
2678-
op: repeat,
2679-
num_captures: name_num
2680-
}))
2681-
} else if p.token.is_keyword_allow_following_colon(keywords::Crate) {
2682-
p.bump();
2683-
TtToken(sp, SpecialVarNt(SpecialMacroVar::CrateMacroVar))
2684-
} else {
2685-
// A nonterminal that matches or not
2686-
let namep = match p.token { token::Ident(_, p) => p, _ => token::Plain };
2687-
let name = p.parse_ident();
2688-
if p.token == token::Colon && p.look_ahead(1, |t| t.is_ident()) {
2689-
p.bump();
2690-
let kindp = match p.token { token::Ident(_, p) => p, _ => token::Plain };
2691-
let nt_kind = p.parse_ident();
2692-
let m = TtToken(sp, MatchNt(name, nt_kind, namep, kindp));
2693-
m
2694-
} else {
2695-
TtToken(sp, SubstNt(name, namep))
2696-
}
2719+
let token_str = p.this_token_to_string();
2720+
p.fatal(format!("incorrect close delimiter: `{}`",
2721+
token_str).index(&FullRange))
2722+
},
2723+
/* we ought to allow different depths of unquotation */
2724+
token::Dollar | token::SubstNt(..) if p.quote_depth > 0u => {
2725+
p.parse_unquoted()
2726+
}
2727+
_ => {
2728+
TtToken(p.span, p.bump_and_get())
26972729
}
2698-
}
2699-
_ => {
2700-
TtToken(p.span, p.bump_and_get())
2701-
}
27022730
}
27032731
}
27042732

0 commit comments

Comments
 (0)