Skip to content

Commit 0b48001

Browse files
committed
auto merge of #17830 : pczarn/rust/interp_tt, r=pnkfelix
Closes #14197 Removes the `matchers` nonterminal. If you're using `$foo:matchers` in a macro, write `$foo:tt` instead. [breaking-change]
2 parents 223ca76 + 00676c8 commit 0b48001

File tree

13 files changed

+539
-435
lines changed

13 files changed

+539
-435
lines changed

src/librustdoc/html/highlight.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,8 @@ fn doit(sess: &parse::ParseSess, mut lexer: lexer::StringReader,
163163

164164
token::Lifetime(..) => "lifetime",
165165
token::DocComment(..) => "doccomment",
166-
token::Underscore | token::Eof | token::Interpolated(..) => "",
166+
token::Underscore | token::Eof | token::Interpolated(..) |
167+
token::MatchNt(..) | token::SubstNt(..) => "",
167168
};
168169

169170
// as mentioned above, use the original source code instead of

src/libsyntax/ast.rs

+83-80
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
// The Rust abstract syntax tree.
1212

13-
use codemap::{Span, Spanned, DUMMY_SP, ExpnId};
13+
use codemap::{Span, Spanned, DUMMY_SP, ExpnId, respan};
1414
use abi::Abi;
1515
use ast_util;
1616
use owned_slice::OwnedSlice;
@@ -713,6 +713,19 @@ impl Delimited {
713713
}
714714
}
715715

716+
/// A sequence of token treesee
717+
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
718+
pub struct SequenceRepetition {
719+
/// The sequence of token trees
720+
pub tts: Vec<TokenTree>,
721+
/// The optional separator
722+
pub separator: Option<token::Token>,
723+
/// Whether the sequence can be repeated zero (*), or one or more times (+)
724+
pub op: KleeneOp,
725+
/// The number of `MatchNt`s that appear in the sequence (and subsequences)
726+
pub num_captures: uint,
727+
}
728+
716729
/// A Kleene-style [repetition operator](http://en.wikipedia.org/wiki/Kleene_star)
717730
/// for token sequences.
718731
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
@@ -727,14 +740,12 @@ pub enum KleeneOp {
727740
/// be passed to syntax extensions using a uniform type.
728741
///
729742
/// If the syntax extension is an MBE macro, it will attempt to match its
730-
/// LHS "matchers" against the provided token tree, and if it finds a
743+
/// LHS token tree against the provided token tree, and if it finds a
731744
/// match, will transcribe the RHS token tree, splicing in any captured
732-
/// `macro_parser::matched_nonterminals` into the `TtNonterminal`s it finds.
745+
/// macro_parser::matched_nonterminals into the `SubstNt`s it finds.
733746
///
734-
/// The RHS of an MBE macro is the only place a `TtNonterminal` or `TtSequence`
735-
/// makes any real sense. You could write them elsewhere but nothing
736-
/// else knows what to do with them, so you'll probably get a syntax
737-
/// error.
747+
/// The RHS of an MBE macro is the only place `SubstNt`s are substituted.
748+
/// Nothing special happens to misnamed or misplaced `SubstNt`s.
738749
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
739750
#[doc="For macro invocations; parsing is delegated to the macro"]
740751
pub enum TokenTree {
@@ -743,90 +754,82 @@ pub enum TokenTree {
743754
/// A delimited sequence of token trees
744755
TtDelimited(Span, Rc<Delimited>),
745756

746-
// These only make sense for right-hand-sides of MBE macros:
757+
// This only makes sense in MBE macros.
747758

748-
/// A Kleene-style repetition sequence with an optional separator.
749-
// FIXME(eddyb) #6308 Use Rc<[TokenTree]> after DST.
750-
TtSequence(Span, Rc<Vec<TokenTree>>, Option<token::Token>, KleeneOp),
751-
/// A syntactic variable that will be filled in by macro expansion.
752-
TtNonterminal(Span, Ident)
759+
/// A kleene-style repetition sequence with a span
760+
// FIXME(eddyb) #12938 Use DST.
761+
TtSequence(Span, Rc<SequenceRepetition>),
753762
}
754763

755764
impl TokenTree {
765+
pub fn len(&self) -> uint {
766+
match *self {
767+
TtToken(_, token::DocComment(_)) => 2,
768+
TtToken(_, token::SubstNt(..)) => 2,
769+
TtToken(_, token::MatchNt(..)) => 3,
770+
TtDelimited(_, ref delimed) => {
771+
delimed.tts.len() + 2
772+
}
773+
TtSequence(_, ref seq) => {
774+
seq.tts.len()
775+
}
776+
TtToken(..) => 0
777+
}
778+
}
779+
780+
pub fn get_tt(&self, index: uint) -> TokenTree {
781+
match (self, index) {
782+
(&TtToken(sp, token::DocComment(_)), 0) => {
783+
TtToken(sp, token::Pound)
784+
}
785+
(&TtToken(sp, token::DocComment(name)), 1) => {
786+
let doc = MetaNameValue(token::intern_and_get_ident("doc"),
787+
respan(sp, LitStr(token::get_name(name), CookedStr)));
788+
let doc = token::NtMeta(P(respan(sp, doc)));
789+
TtDelimited(sp, Rc::new(Delimited {
790+
delim: token::Bracket,
791+
open_span: sp,
792+
tts: vec![TtToken(sp, token::Interpolated(doc))],
793+
close_span: sp,
794+
}))
795+
}
796+
(&TtDelimited(_, ref delimed), _) => {
797+
if index == 0 {
798+
return delimed.open_tt();
799+
}
800+
if index == delimed.tts.len() + 1 {
801+
return delimed.close_tt();
802+
}
803+
delimed.tts[index - 1].clone()
804+
}
805+
(&TtToken(sp, token::SubstNt(name, name_st)), _) => {
806+
let v = [TtToken(sp, token::Dollar),
807+
TtToken(sp, token::Ident(name, name_st))];
808+
v[index]
809+
}
810+
(&TtToken(sp, token::MatchNt(name, kind, name_st, kind_st)), _) => {
811+
let v = [TtToken(sp, token::SubstNt(name, name_st)),
812+
TtToken(sp, token::Colon),
813+
TtToken(sp, token::Ident(kind, kind_st))];
814+
v[index]
815+
}
816+
(&TtSequence(_, ref seq), _) => {
817+
seq.tts[index].clone()
818+
}
819+
_ => panic!("Cannot expand a token tree")
820+
}
821+
}
822+
756823
/// Returns the `Span` corresponding to this token tree.
757824
pub fn get_span(&self) -> Span {
758825
match *self {
759-
TtToken(span, _) => span,
760-
TtDelimited(span, _) => span,
761-
TtSequence(span, _, _, _) => span,
762-
TtNonterminal(span, _) => span,
826+
TtToken(span, _) => span,
827+
TtDelimited(span, _) => span,
828+
TtSequence(span, _) => span,
763829
}
764830
}
765831
}
766832

767-
// Matchers are nodes defined-by and recognized-by the main rust parser and
768-
// language, but they're only ever found inside syntax-extension invocations;
769-
// indeed, the only thing that ever _activates_ the rules in the rust parser
770-
// for parsing a matcher is a matcher looking for the 'matchers' nonterminal
771-
// itself. Matchers represent a small sub-language for pattern-matching
772-
// token-trees, and are thus primarily used by the macro-defining extension
773-
// itself.
774-
//
775-
// MatchTok
776-
// --------
777-
//
778-
// A matcher that matches a single token, denoted by the token itself. So
779-
// long as there's no $ involved.
780-
//
781-
//
782-
// MatchSeq
783-
// --------
784-
//
785-
// A matcher that matches a sequence of sub-matchers, denoted various
786-
// possible ways:
787-
//
788-
// $(M)* zero or more Ms
789-
// $(M)+ one or more Ms
790-
// $(M),+ one or more comma-separated Ms
791-
// $(A B C);* zero or more semi-separated 'A B C' seqs
792-
//
793-
//
794-
// MatchNonterminal
795-
// -----------------
796-
//
797-
// A matcher that matches one of a few interesting named rust
798-
// nonterminals, such as types, expressions, items, or raw token-trees. A
799-
// black-box matcher on expr, for example, binds an expr to a given ident,
800-
// and that ident can re-occur as an interpolation in the RHS of a
801-
// macro-by-example rule. For example:
802-
//
803-
// $foo:expr => 1 + $foo // interpolate an expr
804-
// $foo:tt => $foo // interpolate a token-tree
805-
// $foo:tt => bar! $foo // only other valid interpolation
806-
// // is in arg position for another
807-
// // macro
808-
//
809-
// As a final, horrifying aside, note that macro-by-example's input is
810-
// also matched by one of these matchers. Holy self-referential! It is matched
811-
// by a MatchSeq, specifically this one:
812-
//
813-
// $( $lhs:matchers => $rhs:tt );+
814-
//
815-
// If you understand that, you have closed the loop and understand the whole
816-
// macro system. Congratulations.
817-
pub type Matcher = Spanned<Matcher_>;
818-
819-
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
820-
pub enum Matcher_ {
821-
/// Match one token
822-
MatchTok(token::Token),
823-
/// Match repetitions of a sequence: body, separator, Kleene operator,
824-
/// lo, hi position-in-match-array used:
825-
MatchSeq(Vec<Matcher>, Option<token::Token>, KleeneOp, uint, uint),
826-
/// Parse a Rust NT: name to bind, name of NT, position in match array:
827-
MatchNonterminal(Ident, Ident, uint)
828-
}
829-
830833
pub type Mac = Spanned<Mac_>;
831834

832835
/// Represents a macro invocation. The Path indicates which macro

src/libsyntax/ext/quote.rs

+33-19
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,20 @@ fn mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> P<ast::Expr> {
616616
vec!(mk_name(cx, sp, ident.ident())));
617617
}
618618

619+
token::MatchNt(name, kind, name_style, kind_style) => {
620+
return cx.expr_call(sp,
621+
mk_token_path(cx, sp, "MatchNt"),
622+
vec![mk_ident(cx, sp, name),
623+
mk_ident(cx, sp, kind),
624+
match name_style {
625+
ModName => mk_token_path(cx, sp, "ModName"),
626+
Plain => mk_token_path(cx, sp, "Plain"),
627+
},
628+
match kind_style {
629+
ModName => mk_token_path(cx, sp, "ModName"),
630+
Plain => mk_token_path(cx, sp, "Plain"),
631+
}]);
632+
}
619633
token::Interpolated(_) => panic!("quote! with interpolated token"),
620634

621635
_ => ()
@@ -654,6 +668,25 @@ fn mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> P<ast::Expr> {
654668

655669
fn mk_tt(cx: &ExtCtxt, _: Span, tt: &ast::TokenTree) -> Vec<P<ast::Stmt>> {
656670
match *tt {
671+
ast::TtToken(sp, SubstNt(ident, _)) => {
672+
// tt.extend($ident.to_tokens(ext_cx).into_iter())
673+
674+
let e_to_toks =
675+
cx.expr_method_call(sp,
676+
cx.expr_ident(sp, ident),
677+
id_ext("to_tokens"),
678+
vec!(cx.expr_ident(sp, id_ext("ext_cx"))));
679+
let e_to_toks =
680+
cx.expr_method_call(sp, e_to_toks, id_ext("into_iter"), vec![]);
681+
682+
let e_push =
683+
cx.expr_method_call(sp,
684+
cx.expr_ident(sp, id_ext("tt")),
685+
id_ext("extend"),
686+
vec!(e_to_toks));
687+
688+
vec!(cx.stmt_expr(e_push))
689+
}
657690
ast::TtToken(sp, ref tok) => {
658691
let e_sp = cx.expr_ident(sp, id_ext("_sp"));
659692
let e_tok = cx.expr_call(sp,
@@ -673,25 +706,6 @@ fn mk_tt(cx: &ExtCtxt, _: Span, tt: &ast::TokenTree) -> Vec<P<ast::Stmt>> {
673706
.collect()
674707
},
675708
ast::TtSequence(..) => panic!("TtSequence in quote!"),
676-
ast::TtNonterminal(sp, ident) => {
677-
// tt.extend($ident.to_tokens(ext_cx).into_iter())
678-
679-
let e_to_toks =
680-
cx.expr_method_call(sp,
681-
cx.expr_ident(sp, ident),
682-
id_ext("to_tokens"),
683-
vec!(cx.expr_ident(sp, id_ext("ext_cx"))));
684-
let e_to_toks =
685-
cx.expr_method_call(sp, e_to_toks, id_ext("into_iter"), vec![]);
686-
687-
let e_push =
688-
cx.expr_method_call(sp,
689-
cx.expr_ident(sp, id_ext("tt")),
690-
id_ext("extend"),
691-
vec!(e_to_toks));
692-
693-
vec!(cx.stmt_expr(e_push))
694-
},
695709
}
696710
}
697711

0 commit comments

Comments
 (0)