1 // WARNING WARNING WARNING WARNING WARNING
2 // =======================================
4 // This code also appears in src/doc/unstable-book/src/language-features/plugin.md.
5 // Please keep the two copies in sync! FIXME: have rustdoc read this file
10 #![feature(plugin_registrar, rustc_private)]
13 extern crate syntax_pos;
15 extern crate rustc_plugin;
16 extern crate rustc_driver;
18 use syntax::parse::token::{self, Token};
19 use syntax::tokenstream::TokenTree;
20 use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager};
22 use rustc_plugin::Registry;
24 fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
25 -> Box<dyn MacResult + 'static> {
27 static NUMERALS: &'static [(&'static str, usize)] = &[
28 ("M", 1000), ("CM", 900), ("D", 500), ("CD", 400),
29 ("C", 100), ("XC", 90), ("L", 50), ("XL", 40),
30 ("X", 10), ("IX", 9), ("V", 5), ("IV", 4),
36 &format!("argument should be a single identifier, but got {} arguments", args.len()));
37 return DummyResult::any(sp);
40 let text = match args[0] {
41 TokenTree::Token(Token { kind: token::Ident(s, _), .. }) => s.to_string(),
43 cx.span_err(sp, "argument should be a single identifier");
44 return DummyResult::any(sp);
48 let mut text = &*text;
50 while !text.is_empty() {
51 match NUMERALS.iter().find(|&&(rn, _)| text.starts_with(rn)) {
54 text = &text[rn.len()..];
57 cx.span_err(sp, "invalid Roman numeral");
58 return DummyResult::any(sp);
63 MacEager::expr(cx.expr_usize(sp, total))
67 pub fn plugin_registrar(reg: &mut Registry) {
68 reg.register_macro("rn", expand_rn);