Skip to content

Commit

Permalink
syntax: allow stmt/expr macro invocations to be delimited by [].
Browse files Browse the repository at this point in the history
this is useful for macros like vec! which construct containers
  • Loading branch information
glaebhoerl authored and seanmonstar committed Apr 1, 2014
1 parent b8ef9fd commit be673e7
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 34 deletions.
38 changes: 15 additions & 23 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1881,12 +1881,9 @@ impl<'a> Parser<'a> {
if self.token == token::NOT {
// MACRO INVOCATION expression
self.bump();
match self.token {
token::LPAREN | token::LBRACE => {}
_ => self.fatal("expected open delimiter")
};

let ket = token::flip_delimiter(&self.token);
let ket = token::close_delimiter_for(&self.token)
.unwrap_or_else(|| self.fatal("expected open delimiter"));
self.bump();

let tts = self.parse_seq_to_end(&ket,
Expand Down Expand Up @@ -2109,8 +2106,8 @@ impl<'a> Parser<'a> {
TTTok(p.span, p.bump_and_get())
}

match self.token {
token::EOF => {
match (&self.token, token::close_delimiter_for(&self.token)) {
(&token::EOF, _) => {
let open_braces = self.open_braces.clone();
for sp in open_braces.iter() {
self.span_note(*sp, "Did you mean to close this delimiter?");
Expand All @@ -2119,9 +2116,7 @@ impl<'a> Parser<'a> {
// if we give it one
self.fatal("this file contains an un-closed delimiter ");
}
token::LPAREN | token::LBRACE | token::LBRACKET => {
let close_delim = token::flip_delimiter(&self.token);

(_, Some(close_delim)) => {
// Parse the open delimiter.
self.open_braces.push(self.span);
let mut result = vec!(parse_any_tt_tok(self));
Expand Down Expand Up @@ -2157,13 +2152,12 @@ impl<'a> Parser<'a> {
// the interpolation of Matcher's
maybe_whole!(self, NtMatchers);
let mut name_idx = 0u;
match self.token {
token::LBRACE | token::LPAREN | token::LBRACKET => {
let other_delimiter = token::flip_delimiter(&self.token);
match token::close_delimiter_for(&self.token) {
Some(other_delimiter) => {
self.bump();
self.parse_matcher_subseq_upto(&mut name_idx, &other_delimiter)
}
_ => self.fatal("expected open delimiter")
None => self.fatal("expected open delimiter")
}
}

Expand Down Expand Up @@ -3138,7 +3132,7 @@ impl<'a> Parser<'a> {
let pth = self.parse_path(NoTypesAllowed).path;
self.bump();

let id = if self.token == token::LPAREN || self.token == token::LBRACE {
let id = if token::close_delimiter_for(&self.token).is_some() {
token::special_idents::invalid // no special identifier
} else {
self.parse_ident()
Expand All @@ -3147,10 +3141,9 @@ impl<'a> Parser<'a> {
// check that we're pointing at delimiters (need to check
// again after the `if`, because of `parse_ident`
// consuming more tokens).
let (bra, ket) = match self.token {
token::LPAREN => (token::LPAREN, token::RPAREN),
token::LBRACE => (token::LBRACE, token::RBRACE),
_ => {
let (bra, ket) = match token::close_delimiter_for(&self.token) {
Some(ket) => (self.token.clone(), ket),
None => {
// we only expect an ident if we didn't parse one
// above.
let ident_str = if id == token::special_idents::invalid {
Expand Down Expand Up @@ -4724,15 +4717,14 @@ impl<'a> Parser<'a> {
token::special_idents::invalid // no special identifier
};
// eat a matched-delimiter token tree:
let tts = match self.token {
token::LPAREN | token::LBRACE => {
let ket = token::flip_delimiter(&self.token);
let tts = match token::close_delimiter_for(&self.token) {
Some(ket) => {
self.bump();
self.parse_seq_to_end(&ket,
seq_sep_none(),
|p| p.parse_token_tree())
}
_ => self.fatal("expected open delimiter")
None => self.fatal("expected open delimiter")
};
// single-variant-enum... :
let m = ast::MacInvocTT(pth, tts, EMPTY_CTXT);
Expand Down
18 changes: 7 additions & 11 deletions src/libsyntax/parse/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,21 +297,17 @@ pub fn can_begin_expr(t: &Token) -> bool {
}
}

/// what's the opposite delimiter?
pub fn flip_delimiter(t: &token::Token) -> token::Token {
/// Returns the matching close delimiter if this is an open delimiter,
/// otherwise `None`.
pub fn close_delimiter_for(t: &Token) -> Option<Token> {
match *t {
LPAREN => RPAREN,
LBRACE => RBRACE,
LBRACKET => RBRACKET,
RPAREN => LPAREN,
RBRACE => LBRACE,
RBRACKET => LBRACKET,
_ => fail!()
LPAREN => Some(RPAREN),
LBRACE => Some(RBRACE),
LBRACKET => Some(RBRACKET),
_ => None
}
}



pub fn is_lit(t: &Token) -> bool {
match *t {
LIT_CHAR(_) => true,
Expand Down
23 changes: 23 additions & 0 deletions src/test/run-pass/vec-macro-with-brackets.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(macro_rules)]

macro_rules! vec [
($($e:expr),*) => ({
let mut _temp = ::std::vec::Vec::new();
$(_temp.push($e);)*
_temp
})
]

pub fn main() {
let my_vec = vec![1, 2, 3, 4, 5];
}

5 comments on commit be673e7

@bors
Copy link
Contributor

@bors bors commented on be673e7 Apr 1, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from alexcrichton
at seanmonstar@be673e7

@bors
Copy link
Contributor

@bors bors commented on be673e7 Apr 1, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging seanmonstar/rust/pr/12947 = be673e7 into auto

@bors
Copy link
Contributor

@bors bors commented on be673e7 Apr 1, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seanmonstar/rust/pr/12947 = be673e7 merged ok, testing candidate = 361d791

@bors
Copy link
Contributor

@bors bors commented on be673e7 Apr 1, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bors
Copy link
Contributor

@bors bors commented on be673e7 Apr 1, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fast-forwarding master to auto = 361d791

Please sign in to comment.