/src/test/run-pass-fulldeps/auxiliary/roman_numerals.rs

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