]>
Commit | Line | Data |
---|---|---|
c34b1796 AL |
1 | // Copyright 2015 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 | // force-host | |
12 | ||
13 | #![crate_type="dylib"] | |
14 | #![feature(plugin_registrar, quote, rustc_private)] | |
15 | ||
16 | extern crate syntax; | |
3157f602 | 17 | extern crate syntax_pos; |
c34b1796 | 18 | extern crate rustc; |
92a42be0 | 19 | extern crate rustc_plugin; |
c34b1796 | 20 | |
476ff2be SL |
21 | use syntax::parse::token::{NtExpr, NtPat}; |
22 | use syntax::ast::{Ident, Pat}; | |
3157f602 | 23 | use syntax::tokenstream::{TokenTree}; |
c30ab7b3 | 24 | use syntax::ext::base::{ExtCtxt, MacResult, MacEager}; |
c34b1796 AL |
25 | use syntax::ext::build::AstBuilder; |
26 | use syntax::ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal}; | |
27 | use syntax::ext::tt::macro_parser::{Success, Failure, Error}; | |
c30ab7b3 | 28 | use syntax::ext::tt::macro_parser::parse_failure_msg; |
c34b1796 | 29 | use syntax::ptr::P; |
3157f602 | 30 | use syntax_pos::Span; |
92a42be0 | 31 | use rustc_plugin::Registry; |
c34b1796 | 32 | |
c30ab7b3 | 33 | fn expand_mbe_matches(cx: &mut ExtCtxt, _: Span, args: &[TokenTree]) |
c34b1796 AL |
34 | -> Box<MacResult + 'static> { |
35 | ||
36 | let mbe_matcher = quote_matcher!(cx, $matched:expr, $($pat:pat)|+); | |
c30ab7b3 SL |
37 | let map = match TokenTree::parse(cx, &mbe_matcher, args) { |
38 | Success(map) => map, | |
39 | Failure(_, tok) => { | |
40 | panic!("expected Success, but got Failure: {}", parse_failure_msg(tok)); | |
41 | } | |
42 | Error(_, s) => { | |
43 | panic!("expected Success, but got Error: {}", s); | |
44 | } | |
45 | }; | |
c34b1796 | 46 | |
476ff2be | 47 | let matched_nt = match *map[&Ident::from_str("matched")] { |
c30ab7b3 SL |
48 | MatchedNonterminal(ref nt) => nt.clone(), |
49 | _ => unreachable!(), | |
50 | }; | |
c34b1796 | 51 | |
476ff2be | 52 | let mac_expr = match (&*matched_nt, &*map[&Ident::from_str("pat")]) { |
c30ab7b3 SL |
53 | (&NtExpr(ref matched_expr), &MatchedSeq(ref pats, seq_sp)) => { |
54 | let pats: Vec<P<Pat>> = pats.iter().map(|pat_nt| { | |
55 | match **pat_nt { | |
56 | MatchedNonterminal(ref nt) => match **nt { | |
57 | NtPat(ref pat) => pat.clone(), | |
58 | _ => unreachable!(), | |
59 | }, | |
60 | _ => unreachable!(), | |
c34b1796 | 61 | } |
c30ab7b3 SL |
62 | }).collect(); |
63 | let arm = cx.arm(seq_sp, pats, cx.expr_bool(seq_sp, true)); | |
64 | ||
65 | quote_expr!(cx, | |
66 | match $matched_expr { | |
67 | $arm | |
68 | _ => false | |
69 | } | |
70 | ) | |
c34b1796 | 71 | } |
c30ab7b3 | 72 | _ => unreachable!() |
c34b1796 AL |
73 | }; |
74 | ||
75 | MacEager::expr(mac_expr) | |
76 | } | |
77 | ||
78 | #[plugin_registrar] | |
79 | pub fn plugin_registrar(reg: &mut Registry) { | |
80 | reg.register_macro("matches", expand_mbe_matches); | |
81 | } |