Skip to content

Commit 20e1fd9

Browse files
committed
[WIP] Fix sequence repetitions.
1 parent 3eec292 commit 20e1fd9

File tree

6 files changed

+102
-17
lines changed

6 files changed

+102
-17
lines changed

src/libcollections/macros.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
#[macro_export]
4343
#[stable(feature = "rust1", since = "1.0.0")]
4444
#[allow_internal_unstable]
45-
#[rustc_unsafe_macro]
4645
macro_rules! vec {
4746
($elem:expr; $n:expr) => (
4847
$crate::vec::from_elem($elem, $n)
@@ -58,7 +57,6 @@ macro_rules! vec {
5857
// `slice::into_vec` function which is only available with cfg(test)
5958
// NB see the slice::hack module in slice.rs for more information
6059
#[cfg(test)]
61-
#[rustc_unsafe_macro]
6260
macro_rules! vec {
6361
($elem:expr; $n:expr) => (
6462
$crate::vec::from_elem($elem, $n)

src/librustc/hir/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ use std::fmt;
5555
/// of `Vec` to avoid keeping extra capacity.
5656
pub type HirVec<T> = P<[T]>;
5757

58-
#[rustc_unsafe_macro]
5958
macro_rules! hir_vec {
6059
($elem:expr; $n:expr) => (
6160
$crate::hir::HirVec::from(vec![$elem; $n])

src/librustc/macros.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
#[rustc_unsafe_macro]
1211
macro_rules! enum_from_u32 {
1312
($(#[$attr:meta])* pub enum $name:ident {
1413
$($variant:ident = $e:expr,)*

src/librustc_metadata/macros.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
#[rustc_unsafe_macro]
1211
macro_rules! enum_from_u32 {
1312
($(#[$attr:meta])* pub enum $name:ident {
1413
$($variant:ident = $e:expr,)*

src/libsyntax/ext/tt/macro_rules.rs

Lines changed: 102 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use tokenstream::{self, TokenTree};
2626
use util::small_vector::SmallVector;
2727

2828
use std::cell::RefCell;
29-
use std::collections::{HashMap};
29+
use std::collections::{HashMap, HashSet};
3030
use std::collections::hash_map::{Entry};
3131

3232
struct ParserAnyMacro<'a> {
@@ -366,7 +366,7 @@ fn check_lhs_firsts(cx: &ExtCtxt, lhs: &TokenTree, lhs_: &TokenTree)
366366
match (lhs, lhs_) {
367367
(&TokenTree::Delimited(_, ref tta),
368368
&TokenTree::Delimited(_, ref ttb)) =>
369-
check_matcher_firsts(cx, &tta.tts, &ttb.tts),
369+
check_matcher_firsts(cx, &tta.tts, &ttb.tts, &mut HashSet::new()),
370370
_ => cx.span_bug(lhs.get_span(), "malformed macro lhs")
371371
}
372372
}
@@ -593,7 +593,8 @@ enum AnalysisResult {
593593
Error
594594
}
595595

596-
fn check_matcher_firsts(cx: &ExtCtxt, ma: &[TokenTree], mb: &[TokenTree])
596+
fn check_matcher_firsts(cx: &ExtCtxt, ma: &[TokenTree], mb: &[TokenTree],
597+
visited_spans: &mut HashSet<(Span, Span)>)
597598
-> AnalysisResult {
598599
use self::AnalysisResult::*;
599600
let mut need_disambiguation = false;
@@ -611,7 +612,13 @@ fn check_matcher_firsts(cx: &ExtCtxt, ma: &[TokenTree], mb: &[TokenTree])
611612
// matches A will never match B or vice-versa
612613
// * we find a case that is too complex to handle and reject it
613614
// * we reach the end of the macro
614-
for ((idx_a, ta), tb) in ma.iter().enumerate().zip(mb.iter()) {
615+
for ((idx_a, ta), (idx_b, tb)) in ma.iter().enumerate().zip(mb.iter().enumerate()) {
616+
if visited_spans.contains(&(ta.get_span(), tb.get_span())) {
617+
break
618+
}
619+
620+
visited_spans.insert((ta.get_span(), tb.get_span()));
621+
615622
if match_same_input(ta, tb) {
616623
continue;
617624
}
@@ -625,6 +632,96 @@ fn check_matcher_firsts(cx: &ExtCtxt, ma: &[TokenTree], mb: &[TokenTree])
625632
// not tt, ident, or block (that is, either A or B could match several
626633
// token trees), we cannot know where we should continue the analysis.
627634
match (ta, tb) {
635+
(&TokenTree::Sequence(sp_a, ref seq_a), &TokenTree::Sequence(sp_b, ref seq_b)) => {
636+
let new_tt_a = TokenTree::Sequence(sp_a, tokenstream::SequenceRepetition { op: tokenstream::KleeneOp::ZeroOrMore, .. seq_a.clone() });
637+
let mut new_a = seq_a.tts.iter().map(|x| x.clone()).collect::<Vec<_>>();
638+
if let Some(ref sep) = seq_a.separator { new_a.push(TokenTree::Token(sp_a, sep.clone())) };
639+
new_a.push(new_tt_a);
640+
new_a.extend(ma[idx_a + 1 ..].iter().map(|x| x.clone()));
641+
642+
let new_tt_b = TokenTree::Sequence(sp_b, tokenstream::SequenceRepetition { op: tokenstream::KleeneOp::ZeroOrMore, .. seq_b.clone() });
643+
let mut new_b = seq_b.tts.iter().map(|x| x.clone()).collect::<Vec<_>>();
644+
if let Some(ref sep) = seq_b.separator { new_b.push(TokenTree::Token(sp_b, sep.clone())) };
645+
new_b.push(new_tt_b);
646+
new_b.extend(mb[idx_b + 1 ..].iter().map(|x| x.clone()));
647+
648+
let mut ret = match check_matcher_firsts(cx, &new_a, &mb[idx_b ..], visited_spans) {
649+
Error => return Error,
650+
ret => ret
651+
};
652+
653+
match check_matcher_firsts(cx, &ma[idx_a ..], &new_b, visited_spans) {
654+
Error => return Error,
655+
Unsure => ret = Unsure,
656+
Ok => ()
657+
};
658+
659+
if seq_a.op == tokenstream::KleeneOp::ZeroOrMore {
660+
match check_matcher_firsts(cx, &ma[idx_a + 1 ..], &mb[idx_b ..], visited_spans) {
661+
Error => return Error,
662+
Unsure => ret = Unsure,
663+
Ok => ()
664+
};
665+
}
666+
667+
if seq_b.op == tokenstream::KleeneOp::ZeroOrMore {
668+
match check_matcher_firsts(cx, &ma[idx_a ..], &mb[idx_b + 1 ..], visited_spans) {
669+
Error => return Error,
670+
Unsure => ret = Unsure,
671+
Ok => ()
672+
};
673+
}
674+
675+
return ret;
676+
}
677+
678+
(&TokenTree::Sequence(sp, ref seq), _) => {
679+
// unroll 1 step.
680+
let new_tt = TokenTree::Sequence(sp, tokenstream::SequenceRepetition { op: tokenstream::KleeneOp::ZeroOrMore, .. seq.clone() });
681+
let mut new_a = seq.tts.iter().map(|x| x.clone()).collect::<Vec<_>>();
682+
if let Some(ref sep) = seq.separator { new_a.push(TokenTree::Token(sp, sep.clone())) };
683+
new_a.push(new_tt);
684+
new_a.extend(ma[idx_a + 1 ..].iter().map(|x| x.clone()));
685+
let mut ret = match check_matcher_firsts(cx, &new_a, &mb[idx_b ..], visited_spans) {
686+
Error => return Error,
687+
ret => ret
688+
};
689+
690+
if seq.op == tokenstream::KleeneOp::ZeroOrMore {
691+
match check_matcher_firsts(cx, &ma[idx_a + 1 ..], &mb[idx_b ..], visited_spans) {
692+
Error => return Error,
693+
Unsure => ret = Unsure,
694+
Ok => ()
695+
};
696+
}
697+
698+
return ret;
699+
}
700+
701+
(_, &TokenTree::Sequence(sp, ref seq)) => {
702+
// unroll 1 step.
703+
let new_tt = TokenTree::Sequence(sp, tokenstream::SequenceRepetition { op: tokenstream::KleeneOp::ZeroOrMore, .. seq.clone() });
704+
let mut new_b = seq.tts.iter().map(|x| x.clone()).collect::<Vec<_>>();
705+
if let Some(ref sep) = seq.separator { new_b.push(TokenTree::Token(sp, sep.clone())) };
706+
new_b.push(new_tt);
707+
new_b.extend(mb[idx_b + 1 ..].iter().map(|x| x.clone()));
708+
let mut ret = match check_matcher_firsts(cx, &ma[idx_a ..], &new_b, visited_spans) {
709+
Error => return Error,
710+
ret => ret
711+
};
712+
713+
if seq.op == tokenstream::KleeneOp::ZeroOrMore {
714+
match check_matcher_firsts(cx, &ma[idx_a ..], &mb[idx_b + 1 ..], visited_spans) {
715+
Error => return Error,
716+
Unsure => ret = Unsure,
717+
Ok => ()
718+
};
719+
720+
}
721+
722+
return ret;
723+
}
724+
628725
(&TokenTree::Token(_, MatchNt(_, nta)),
629726
&TokenTree::Token(_, MatchNt(_, ntb))) =>
630727
if !(nt_is_single_tt(nta) && nt_is_single_tt(ntb)) {
@@ -638,12 +735,6 @@ fn check_matcher_firsts(cx: &ExtCtxt, ma: &[TokenTree], mb: &[TokenTree])
638735
// followed by the end of the macro invocation, then we can accept
639736
// it.
640737

641-
(&TokenTree::Sequence(_, _), _) |
642-
(_, &TokenTree::Sequence(_, _)) =>
643-
return if only_simple_tokens(&ma[idx_a..]) && !need_disambiguation {
644-
Unsure
645-
} else { Error },
646-
647738
(_ ,&TokenTree::Token(_, MatchNt(_, nt))) if !nt_is_single_tt(nt) =>
648739
return if only_simple_tokens(&ma[idx_a..]) && !need_disambiguation {
649740
Unsure
@@ -714,7 +805,7 @@ fn check_matcher_firsts(cx: &ExtCtxt, ma: &[TokenTree], mb: &[TokenTree])
714805
(&TokenTree::Delimited(_, ref d1),
715806
&TokenTree::Delimited(_, ref d2)) => {
716807
// they have the same delim. as above.
717-
match check_matcher_firsts(cx, &d1.tts, &d2.tts) {
808+
match check_matcher_firsts(cx, &d1.tts, &d2.tts, visited_spans) {
718809
Ok => return Ok,
719810
Unsure => continue,
720811
Error => {

src/libsyntax/feature_gate.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ macro_rules! setter {
4848
}}
4949
}
5050

51-
#[rustc_unsafe_macro]
5251
macro_rules! declare_features {
5352
($((active, $feature: ident, $ver: expr, $issue: expr)),+) => {
5453
/// Represents active features that are currently being implemented or

0 commit comments

Comments
 (0)