]>
Commit | Line | Data |
---|---|---|
9e0c209e SL |
1 | // Copyright 2016 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | #![allow(unused_parens)] | |
12 | #![feature(plugin)] | |
13 | #![feature(plugin_registrar)] | |
14 | #![feature(rustc_private)] | |
c30ab7b3 | 15 | #![plugin(proc_macro_plugin)] |
9e0c209e SL |
16 | |
17 | extern crate rustc_plugin; | |
9e0c209e SL |
18 | extern crate syntax; |
19 | ||
9e0c209e SL |
20 | use rustc_plugin::Registry; |
21 | ||
32a655c1 SL |
22 | use syntax::ext::base::SyntaxExtension; |
23 | use syntax::parse::token::Token; | |
24 | use syntax::symbol::Symbol; | |
9e0c209e SL |
25 | use syntax::tokenstream::{TokenTree, TokenStream}; |
26 | ||
27 | #[plugin_registrar] | |
28 | pub fn plugin_registrar(reg: &mut Registry) { | |
32a655c1 SL |
29 | reg.register_syntax_extension(Symbol::intern("cond"), |
30 | SyntaxExtension::ProcMacro(Box::new(cond))); | |
9e0c209e SL |
31 | } |
32 | ||
32a655c1 SL |
33 | fn cond(input: TokenStream) -> TokenStream { |
34 | let mut conds = Vec::new(); | |
8bb4bdeb | 35 | let mut input = input.trees().peekable(); |
32a655c1 | 36 | while let Some(tree) = input.next() { |
8bb4bdeb XL |
37 | let mut cond = match tree { |
38 | TokenTree::Delimited(_, ref delimited) => delimited.stream(), | |
32a655c1 SL |
39 | _ => panic!("Invalid input"), |
40 | }; | |
8bb4bdeb | 41 | let mut trees = cond.trees(); |
32a655c1 SL |
42 | let test = trees.next(); |
43 | let rhs = trees.collect::<TokenStream>(); | |
44 | if rhs.is_empty() { | |
45 | panic!("Invalid macro usage in cond: {}", cond); | |
46 | } | |
47 | let is_else = match test { | |
48 | Some(TokenTree::Token(_, Token::Ident(ident))) if ident.name == "else" => true, | |
49 | _ => false, | |
50 | }; | |
51 | conds.push(if is_else || input.peek().is_none() { | |
52 | qquote!({ unquote rhs }) | |
53 | } else { | |
54 | qquote!(if unquote(test.unwrap()) { unquote rhs } else) | |
55 | }); | |
56 | } | |
57 | ||
58 | conds.into_iter().collect() | |
9e0c209e | 59 | } |