Skip to content

Commit 7f9b1fb

Browse files
committed
Add new syntax for interpolation and repetition, and allow the transcription of separators.
1 parent 62db570 commit 7f9b1fb

File tree

4 files changed

+70
-39
lines changed

4 files changed

+70
-39
lines changed

src/libsyntax/ast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ enum token_tree {
379379
tt_delim(~[token_tree]),
380380
tt_flat(span, token::token),
381381
/* These only make sense for right-hand-sides of MBE macros*/
382-
tt_dotdotdot(span, ~[token_tree]),
382+
tt_dotdotdot(span, ~[token_tree], option<token::token>, bool),
383383
tt_interpolate(span, ident)
384384
}
385385

src/libsyntax/ext/tt/transcribe.rs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ type tt_frame = @{
1818
readme: ~[ast::token_tree],
1919
mut idx: uint,
2020
dotdotdoted: bool,
21-
up: tt_frame_up
21+
sep: option<token>,
22+
up: tt_frame_up,
2223
};
2324

2425
type tt_reader = @{
@@ -43,7 +44,7 @@ fn new_tt_reader(span_diagnostic: span_handler, itr: @interner<@str>,
4344
-> tt_reader {
4445
let r = @{span_diagnostic: span_diagnostic, interner: itr,
4546
mut cur: @{readme: src, mut idx: 0u, dotdotdoted: false,
46-
up: tt_frame_up(option::none)},
47+
sep: none, up: tt_frame_up(option::none)},
4748
interpolations: alt interp { /* just a convienience */
4849
none { std::map::box_str_hash::<@arb_depth>() }
4950
some(x) { x }
@@ -59,7 +60,7 @@ fn new_tt_reader(span_diagnostic: span_handler, itr: @interner<@str>,
5960

6061
pure fn dup_tt_frame(&&f: tt_frame) -> tt_frame {
6162
@{readme: f.readme, mut idx: f.idx, dotdotdoted: f.dotdotdoted,
62-
up: alt f.up {
63+
sep: f.sep, up: alt f.up {
6364
tt_frame_up(some(up_frame)) {
6465
tt_frame_up(some(dup_tt_frame(up_frame)))
6566
}
@@ -114,7 +115,7 @@ fn lockstep_iter_size(&&t: token_tree, &&r: tt_reader) -> lis {
114115
}
115116
}
116117
alt t {
117-
tt_delim(tts) | tt_dotdotdot(_, tts) {
118+
tt_delim(tts) | tt_dotdotdot(_, tts, _, _) {
118119
vec::foldl(lis_unconstrained, tts, {|lis, tt|
119120
lis_merge(lis, lockstep_iter_size(tt, r)) })
120121
}
@@ -155,6 +156,13 @@ fn tt_next_token(&&r: tt_reader) -> {tok: token, sp: span} {
155156
} else {
156157
r.cur.idx = 0u;
157158
r.repeat_idx[r.repeat_idx.len() - 1u] += 1u;
159+
alt r.cur.sep {
160+
some(tk) {
161+
r.cur_tok = tk; /* repeat same span, I guess */
162+
ret ret_val;
163+
}
164+
none {}
165+
}
158166
}
159167
}
160168
/* if `tt_delim`s could be 0-length, we'd need to be able to switch
@@ -164,15 +172,15 @@ fn tt_next_token(&&r: tt_reader) -> {tok: token, sp: span} {
164172
alt r.cur.readme[r.cur.idx] {
165173
tt_delim(tts) {
166174
r.cur = @{readme: tts, mut idx: 0u, dotdotdoted: false,
167-
up: tt_frame_up(option::some(r.cur)) };
175+
sep: none, up: tt_frame_up(option::some(r.cur)) };
168176
}
169177
tt_flat(sp, tok) {
170178
r.cur_span = sp; r.cur_tok = tok;
171179
r.cur.idx += 1u;
172180
ret ret_val;
173181
}
174-
tt_dotdotdot(sp, tts) {
175-
alt lockstep_iter_size(tt_dotdotdot(sp, tts), r) {
182+
tt_dotdotdot(sp, tts, sep, zerok) {
183+
alt lockstep_iter_size(tt_dotdotdot(sp, tts, sep, zerok), r) {
176184
lis_unconstrained {
177185
r.span_diagnostic.span_fatal(
178186
copy r.cur_span, /* blame macro writer */
@@ -183,10 +191,14 @@ fn tt_next_token(&&r: tt_reader) -> {tok: token, sp: span} {
183191
r.span_diagnostic.span_fatal(sp, msg);
184192
}
185193
lis_constraint(len, _) {
194+
if len == 0 && !zerok {
195+
r.span_diagnostic.span_fatal(sp, "this must repeat \
196+
at least once");
197+
}
186198
vec::push(r.repeat_len, len);
187199
vec::push(r.repeat_idx, 0u);
188200
r.cur = @{readme: tts, mut idx: 0u, dotdotdoted: true,
189-
up: tt_frame_up(option::some(r.cur)) };
201+
sep: sep, up: tt_frame_up(option::some(r.cur)) };
190202
}
191203
}
192204
}

src/libsyntax/parse/parser.rs

Lines changed: 48 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1130,6 +1130,26 @@ class parser {
11301130
ret e;
11311131
}
11321132

1133+
fn parse_sep_and_zerok() -> (option<token::token>, bool) {
1134+
if self.token == token::BINOP(token::STAR)
1135+
|| self.token == token::BINOP(token::PLUS) {
1136+
let zerok = self.token == token::BINOP(token::STAR);
1137+
self.bump();
1138+
ret (none, zerok);
1139+
} else {
1140+
let sep = self.token;
1141+
self.bump();
1142+
if self.token == token::BINOP(token::STAR)
1143+
|| self.token == token::BINOP(token::PLUS) {
1144+
let zerok = self.token == token::BINOP(token::STAR);
1145+
self.bump();
1146+
ret (some(sep), zerok);
1147+
} else {
1148+
self.fatal("expected '*' or '+'");
1149+
}
1150+
}
1151+
}
1152+
11331153
fn parse_token_tree() -> token_tree {
11341154
/// what's the opposite delimiter?
11351155
fn flip(&t: token::token) -> token::token {
@@ -1142,12 +1162,6 @@ class parser {
11421162
}
11431163

11441164
fn parse_tt_flat(p: parser, delim_ok: bool) -> token_tree {
1145-
if p.eat_keyword("many") && p.quote_depth > 0u {
1146-
let seq = p.parse_seq(token::LPAREN, token::RPAREN,
1147-
seq_sep_none(),
1148-
|p| p.parse_token_tree());
1149-
ret tt_dotdotdot(seq.span, seq.node);
1150-
}
11511165
alt p.token {
11521166
token::RPAREN | token::RBRACE | token::RBRACKET
11531167
if !delim_ok {
@@ -1161,7 +1175,16 @@ class parser {
11611175
token::DOLLAR if p.quote_depth > 0u {
11621176
p.bump();
11631177
let sp = p.span;
1164-
ret tt_interpolate(sp, p.parse_ident());
1178+
1179+
if p.token == token::LPAREN {
1180+
let seq = p.parse_seq(token::LPAREN, token::RPAREN,
1181+
seq_sep_none(),
1182+
|p| p.parse_token_tree());
1183+
let (s, z) = p.parse_sep_and_zerok();
1184+
ret tt_dotdotdot(mk_sp(sp.lo ,p.span.hi), seq.node, s, z);
1185+
} else {
1186+
ret tt_interpolate(sp, p.parse_ident());
1187+
}
11651188
}
11661189
_ { /* ok */ }
11671190
}
@@ -1221,34 +1244,32 @@ class parser {
12211244

12221245
fn parse_matcher(name_idx: @mut uint) -> matcher {
12231246
let lo = self.span.lo;
1224-
let mut sep = none;
1225-
if self.eat_keyword("sep") { sep = some(self.token); self.bump(); }
12261247

1227-
let m = if self.is_keyword("many")||self.is_keyword("at_least_one") {
1228-
let zero_ok = self.is_keyword("many");
1248+
let m = if self.token == token::DOLLAR {
12291249
self.bump();
1230-
let ms = (self.parse_seq(token::LPAREN, token::RPAREN,
1231-
common::seq_sep_none(),
1232-
|p| p.parse_matcher(name_idx)).node);
1233-
if ms.len() == 0u {
1234-
self.fatal("repetition body must be nonempty");
1250+
if self.token == token::LPAREN {
1251+
let ms = (self.parse_seq(token::LPAREN, token::RPAREN,
1252+
common::seq_sep_none(),
1253+
|p| p.parse_matcher(name_idx)).node);
1254+
if ms.len() == 0u {
1255+
self.fatal("repetition body must be nonempty");
1256+
}
1257+
let (sep, zerok) = self.parse_sep_and_zerok();
1258+
mtc_rep(ms, sep, zerok)
1259+
} else {
1260+
let bound_to = self.parse_ident();
1261+
self.expect(token::COLON);
1262+
let nt_name = self.parse_ident();
1263+
let m = mtc_bb(bound_to, nt_name, *name_idx);
1264+
*name_idx += 1u;
1265+
m
12351266
}
1236-
mtc_rep(ms, sep, zero_ok)
1237-
} else if option::is_some(sep) {
1238-
self.fatal("`sep <tok>` must preceed `many` or `at_least_one`");
1239-
} else if self.eat_keyword("parse") {
1240-
let bound_to = self.parse_ident();
1241-
self.expect(token::EQ);
1242-
let nt_name = self.parse_ident();
1243-
1244-
let m = mtc_bb(bound_to, nt_name, *name_idx);
1245-
*name_idx += 1u;
1246-
m
12471267
} else {
12481268
let m = mtc_tok(self.token);
12491269
self.bump();
12501270
m
12511271
};
1272+
12521273
ret spanned(lo, self.span.hi, m);
12531274
}
12541275

src/libsyntax/parse/token.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -274,9 +274,7 @@ fn contextual_keyword_table() -> hashmap<str, ()> {
274274
"self", "send", "static",
275275
"to",
276276
"use",
277-
"with",
278-
/* temp */
279-
"sep", "many", "at_least_one", "parse"
277+
"with"
280278
];
281279
for keys.each |word| {
282280
words.insert(word, ());

0 commit comments

Comments
 (0)