/src/test/auxiliary/roman_numerals.rs

https://gitlab.com/pranith/rust · Rust · 71 lines · 45 code · 11 blank · 15 comment · 3 complexity · 08359ff958b81694adaf2ad4460317ba MD5 · raw file

  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. // force-host
  11. #![crate_type="dylib"]
  12. #![feature(plugin_registrar, rustc_private)]
  13. #![feature(slice_patterns)]
  14. extern crate syntax;
  15. extern crate rustc;
  16. use syntax::codemap::Span;
  17. use syntax::parse::token;
  18. use syntax::ast::{TokenTree, TtToken};
  19. use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager};
  20. use syntax::ext::build::AstBuilder; // trait for expr_usize
  21. use rustc::plugin::Registry;
  22. // WARNING WARNING WARNING WARNING WARNING
  23. // =======================================
  24. //
  25. // This code also appears in src/doc/guide-plugin.md. Please keep
  26. // the two copies in sync! FIXME: have rustdoc read this file
  27. fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
  28. -> Box<MacResult + 'static> {
  29. static NUMERALS: &'static [(&'static str, usize)] = &[
  30. ("M", 1000), ("CM", 900), ("D", 500), ("CD", 400),
  31. ("C", 100), ("XC", 90), ("L", 50), ("XL", 40),
  32. ("X", 10), ("IX", 9), ("V", 5), ("IV", 4),
  33. ("I", 1)];
  34. let text = match args {
  35. [TtToken(_, token::Ident(s, _))] => token::get_ident(s).to_string(),
  36. _ => {
  37. cx.span_err(sp, "argument should be a single identifier");
  38. return DummyResult::any(sp);
  39. }
  40. };
  41. let mut text = &*text;
  42. let mut total = 0;
  43. while !text.is_empty() {
  44. match NUMERALS.iter().find(|&&(rn, _)| text.starts_with(rn)) {
  45. Some(&(rn, val)) => {
  46. total += val;
  47. text = &text[rn.len()..];
  48. }
  49. None => {
  50. cx.span_err(sp, "invalid Roman numeral");
  51. return DummyResult::any(sp);
  52. }
  53. }
  54. }
  55. MacEager::expr(cx.expr_usize(sp, total))
  56. }
  57. #[plugin_registrar]
  58. pub fn plugin_registrar(reg: &mut Registry) {
  59. reg.register_macro("rn", expand_rn);
  60. }