]> git.lizzy.rs Git - rust.git/blob - src/test/auxiliary/roman_numerals.rs
rollup merge of #21438: taralx/kill-racycell
[rust.git] / src / test / auxiliary / roman_numerals.rs
1 // Copyright 2014 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)]
15
16 extern crate syntax;
17 extern crate rustc;
18
19 use syntax::codemap::Span;
20 use syntax::parse::token;
21 use syntax::ast::{TokenTree, TtToken};
22 use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacExpr};
23 use syntax::ext::build::AstBuilder;  // trait for expr_usize
24 use rustc::plugin::Registry;
25
26 // WARNING WARNING WARNING WARNING WARNING
27 // =======================================
28 //
29 // This code also appears in src/doc/guide-plugin.md. Please keep
30 // the two copies in sync!  FIXME: have rustdoc read this file
31
32 fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
33         -> Box<MacResult + 'static> {
34
35     static NUMERALS: &'static [(&'static str, uint)] = &[
36         ("M", 1000), ("CM", 900), ("D", 500), ("CD", 400),
37         ("C",  100), ("XC",  90), ("L",  50), ("XL",  40),
38         ("X",   10), ("IX",   9), ("V",   5), ("IV",   4),
39         ("I",    1)];
40
41     let text = match args {
42         [TtToken(_, token::Ident(s, _))] => token::get_ident(s).to_string(),
43         _ => {
44             cx.span_err(sp, "argument should be a single identifier");
45             return DummyResult::any(sp);
46         }
47     };
48
49     let mut text = text.as_slice();
50     let mut total = 0u;
51     while !text.is_empty() {
52         match NUMERALS.iter().find(|&&(rn, _)| text.starts_with(rn)) {
53             Some(&(rn, val)) => {
54                 total += val;
55                 text = text.slice_from(rn.len());
56             }
57             None => {
58                 cx.span_err(sp, "invalid Roman numeral");
59                 return DummyResult::any(sp);
60             }
61         }
62     }
63
64     MacExpr::new(cx.expr_usize(sp, total))
65 }
66
67 #[plugin_registrar]
68 pub fn plugin_registrar(reg: &mut Registry) {
69     reg.register_macro("rn", expand_rn);
70 }