Allow interpolations of all the nt_*s.

This commit is contained in:
Paul Stansifer 2012-08-01 14:34:35 -07:00
parent 0646890f63
commit 7129883b51
3 changed files with 57 additions and 12 deletions

View File

@ -24,7 +24,10 @@ fn add_new_extension(cx: ext_ctxt, sp: span, name: ident,
ms(match_nonterminal(@~"lhs",@~"matchers", 0u)),
ms(match_tok(FAT_ARROW)),
ms(match_nonterminal(@~"rhs",@~"tt", 1u)),
], some(SEMI), false, 0u, 2u))];
], some(SEMI), false, 0u, 2u)),
//to phase into semicolon-termination instead of
//semicolon-separation
ms(match_seq(~[ms(match_tok(SEMI))], none, true, 2u, 2u))];
// Parse the macro_rules! invocation (`none` is for no interpolations):

View File

@ -120,23 +120,29 @@ macro_rules! maybe_whole_expr {
}
macro_rules! maybe_whole {
{$p:expr, $constructor:path} => { alt copy $p.token {
INTERPOLATED($constructor(x)) { $p.bump(); return x; }
{$p:expr, $constructor:ident} => { alt copy $p.token {
INTERPOLATED(token::$constructor(x)) { $p.bump(); return x; }
_ {}
}} ;
{deref $p:expr, $constructor:ident} => { alt copy $p.token {
INTERPOLATED(token::$constructor(x)) { $p.bump(); return *x; }
_ {}
}} ;
{some $p:expr, $constructor:ident} => { alt copy $p.token {
INTERPOLATED(token::$constructor(x)) { $p.bump(); return some(x); }
_ {}
}} ;
{pair_empty $p:expr, $constructor:ident} => { alt copy $p.token {
INTERPOLATED(token::$constructor(x)) { $p.bump(); return (~[], x); }
_ {}
}}
}
/* ident is handled by common.rs */
fn dummy() {
/* we will need this to bootstrap maybe_whole! */
#macro[[#maybe_whole_path[p],
alt p.token {
INTERPOLATED(token::nt_path(pt)) { p.bump(); return pt; }
_ {} }]];
}
class parser {
let sess: parse_sess;
let cfg: crate_cfg;
@ -389,6 +395,8 @@ class parser {
}
fn parse_ty(colons_before_params: bool) -> @ty {
maybe_whole!{self, nt_ty};
let lo = self.span.lo;
alt self.maybe_parse_dollar_mac() {
@ -610,6 +618,7 @@ class parser {
parse_ident: fn(parser) -> ident,
parse_last_ident: fn(parser) -> ident) -> @path {
maybe_whole!{self, nt_path};
let lo = self.span.lo;
let global = self.eat(token::MOD_SEP);
let mut ids = ~[];
@ -638,6 +647,7 @@ class parser {
fn parse_path_with_tps(colons: bool) -> @path {
debug!{"parse_path_with_tps(colons=%b)", colons};
maybe_whole!{self, nt_path};
let lo = self.span.lo;
let path = self.parse_path_without_tps();
if colons && !self.eat(token::MOD_SEP) {
@ -1067,6 +1077,8 @@ class parser {
}
fn parse_token_tree() -> token_tree {
maybe_whole!{deref self, nt_tt};
fn parse_tt_tok(p: parser, delim_ok: bool) -> token_tree {
alt p.token {
token::RPAREN | token::RBRACE | token::RBRACKET
@ -1115,6 +1127,9 @@ class parser {
}
fn parse_matchers() -> ~[matcher] {
// unification of matchers and token_trees would vastly improve
// the interpolation of matchers
maybe_whole!{self, nt_matchers};
let name_idx = @mut 0u;
return self.parse_matcher_subseq(
name_idx, token::LBRACE, token::RBRACE);
@ -1601,6 +1616,8 @@ class parser {
}
fn parse_pat(refutable: bool) -> @pat {
maybe_whole!{self, nt_pat};
let lo = self.span.lo;
let mut hi = self.span.hi;
let mut pat;
@ -1830,6 +1847,8 @@ class parser {
}
fn parse_stmt(+first_item_attrs: ~[attribute]) -> @stmt {
maybe_whole!{self, nt_stmt};
fn check_expected_item(p: parser, current_attrs: ~[attribute]) {
// If we have attributes then we should have an item
if vec::is_not_empty(current_attrs) {
@ -1890,6 +1909,8 @@ class parser {
fn parse_inner_attrs_and_block(parse_attrs: bool)
-> (~[attribute], blk) {
maybe_whole!{pair_empty self, nt_block};
fn maybe_parse_inner_attrs_and_next(p: parser, parse_attrs: bool) ->
{inner: ~[attribute], next: ~[attribute]} {
if parse_attrs {
@ -2735,6 +2756,8 @@ class parser {
fn parse_item(+attrs: ~[attribute], vis: visibility)
-> option<@item> {
maybe_whole!{some self,nt_item};
let lo = self.span.lo;
let (ident, item_, extra_attrs) = if self.eat_keyword(~"const") {
self.parse_item_const()

View File

@ -0,0 +1,19 @@
macro_rules! overly_complicated {
{$fnname:ident, $arg:ident, $ty:ty, $body:block, $val:expr, $pat:pat, $res:path} =>
{
fn $fnname($arg: $ty) -> option<$ty> $body
alt $fnname($val) {
some($pat) {
$res
}
_ { fail; }
}
}
}
fn main() {
assert overly_complicated!(f, x, option<uint>, { return some(x); },
some(8u), some(y), y) == 8u
}