Advertisement
Guest User

Untitled

a guest
Apr 27th, 2015
203
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.15 KB | None | 0 0
  1. #![allow(non_camel_case_types, dead_code, non_snake_case, unused_variables)]
  2.  
  3. use std::borrow::{Cow, IntoCow};
  4. use std::fmt::{self, Formatter};
  5. use std::ascii::AsciiExt;
  6.  
  7. use self::FragmentSpecifier::*;
  8.  
  9. fn check_terminal(s: &str) {
  10. assert!(s.is_ascii());
  11. assert!(s.len() > 0);
  12. for c in s.chars() {
  13. assert!(!c.is_whitespace());
  14. }
  15. }
  16.  
  17. fn check_ident(s: &str) {
  18. check_terminal(s);
  19. let first = s.chars().next().unwrap();
  20. assert!('a' <= first && first <= 'z' ||
  21. 'A' <= first && first <= 'Z' ||
  22. '_' == first);
  23. }
  24.  
  25. #[derive(Clone)]
  26. struct Terminal { s: Cow<'static, str> }
  27. fn Terminal<S:IntoCow<'static, str>>(s: S) -> Terminal {
  28. let s = s.into_cow();
  29. check_terminal(&s);
  30. Terminal { s: s }
  31. }
  32. #[derive(Clone)]
  33. struct Ident { s: Cow<'static, str> }
  34. fn Ident<S:IntoCow<'static, str>>(s: S) -> Ident {
  35. let s = s.into_cow();
  36. check_ident(&s);
  37. Ident { s: s }
  38. }
  39.  
  40. #[derive(Clone)]
  41. enum Token { T(Terminal), NT(NonTerm), }
  42. trait IntoToken: Sized { fn into_token(self) -> Token; }
  43. trait ToToken { fn to_token(&self) -> Token; }
  44. impl ToToken for &'static str {
  45. fn to_token(&self) -> Token { self.into_token() }
  46. }
  47. impl IntoToken for Token { fn into_token(self) -> Token { self } }
  48. impl IntoToken for &'static str {
  49. fn into_token(self) -> Token { Token::T(Terminal(self)) }
  50. }
  51. impl IntoToken for String {
  52. fn into_token(self) -> Token { Token::T(Terminal(self)) }
  53. }
  54. impl IntoToken for Ident {
  55. fn into_token(self) -> Token { Token::T(Terminal(self.s)) }
  56. }
  57. impl ToToken for Ident {
  58. fn to_token(&self) -> Token { Token::T(Terminal(self.s.clone())) }
  59. }
  60. impl IntoToken for Terminal {
  61. fn into_token(self) -> Token { Token::T(self) }
  62. }
  63. impl ToToken for Terminal {
  64. fn to_token(&self) -> Token { Token::T(Terminal(self.s.clone())) }
  65. }
  66. impl IntoToken for NonTerm {
  67. fn into_token(self) -> Token { Token::NT(self) }
  68. }
  69. impl ToToken for SimpleNT {
  70. fn to_token(&self) -> Token { Token::NT(NonTerm::Simple(self.clone())) }
  71. }
  72. impl ToToken for ComplexNT {
  73. fn to_token(&self) -> Token {
  74. Token::NT(NonTerm::Complex(Box::new(self.clone())))
  75. }
  76. }
  77. #[derive(Clone)]
  78. enum NonTerm { Simple(SimpleNT), Complex(Box<ComplexNT>), }
  79. #[derive(Clone)]
  80. struct SimpleNT { id: Ident, spec: FragmentSpecifier }
  81. fn SimpleNT<S:IntoCow<'static, str>>(id: S, spec: FragmentSpecifier) -> SimpleNT {
  82. SimpleNT { id: Ident(id), spec: spec }
  83. }
  84. #[derive(Clone)]
  85. struct ComplexNT { tokens: Vec<Token>, delim: Option<Token>, rep: Repeat }
  86. fn ComplexNT<'a, I:Iterator<Item=&'a ToToken>>(toks: I, delim: Option<Token>, rep: Repeat) -> ComplexNT{
  87. ComplexNT {
  88. tokens: toks.map(|x|x.to_token()).collect(),
  89. delim: delim,
  90. rep: rep
  91. }
  92. }
  93. fn RepeatWith<'a, I:Iterator<Item=&'a ToToken>, D:IntoToken>(toks: I, delim: D) -> ComplexNT {
  94. ComplexNT(toks, Some(delim.into_token()), Repeat::ZeroOrMore)
  95. }
  96. fn RepeatWithPlus<D:IntoToken>(toks: Vec<&ToToken>, delim: D) -> ComplexNT {
  97. ComplexNT(toks.into_iter(), Some(delim.into_token()), Repeat::OneOrMore)
  98. }
  99. fn Repeat(toks: Vec<&ToToken>) -> ComplexNT {
  100. ComplexNT(toks.into_iter(), None, Repeat::ZeroOrMore)
  101. }
  102. fn RepeatPlus(toks: Vec<&ToToken>) -> ComplexNT {
  103. ComplexNT(toks.into_iter(), None, Repeat::OneOrMore)
  104. }
  105.  
  106. #[derive(Clone)]
  107. enum Repeat { ZeroOrMore, OneOrMore }
  108. #[derive(Clone)]
  109. enum FragmentSpecifier {
  110. pat, expr, ty, stmt, path, block, ident, tt, item, meta
  111. }
  112.  
  113. #[derive(Clone)]
  114. enum TokenTree {
  115. Token(Token),
  116. Group(Grouping, Vec<TokenTree>),
  117. }
  118.  
  119. #[derive(Clone)]
  120. enum Grouping { Parens, Brackets, Braces }
  121.  
  122. trait ToTokenTree { fn to_tokentree(&self) -> TokenTree; }
  123. trait IntoTokenTree { fn into_tokentree(self) -> TokenTree; }
  124.  
  125. impl<T:ToToken> ToTokenTree for T {
  126. fn to_tokentree(&self) -> TokenTree {
  127. TokenTree::Token(self.to_token().clone())
  128. }
  129. }
  130.  
  131. impl std::fmt::Display for Terminal {
  132. fn fmt(&self, w: &mut Formatter) -> fmt::Result { write!(w, "{}", self.s) }
  133. }
  134. impl std::fmt::Display for Ident {
  135. fn fmt(&self, w: &mut Formatter) -> fmt::Result { write!(w, "{}", self.s) }
  136. }
  137. impl std::fmt::Display for FragmentSpecifier {
  138. fn fmt(&self, w: &mut Formatter) -> fmt::Result {
  139. let name = match *self {
  140. FragmentSpecifier::pat => "pat",
  141. FragmentSpecifier::expr => "expr",
  142. FragmentSpecifier::ty => "ty",
  143. FragmentSpecifier::stmt => "stmt",
  144. FragmentSpecifier::path => "path",
  145. FragmentSpecifier::block => "block",
  146. FragmentSpecifier::ident => "ident",
  147. FragmentSpecifier::tt => "tt",
  148. FragmentSpecifier::item => "item",
  149. FragmentSpecifier::meta => "meta",
  150. };
  151. write!(w, "{}", name)
  152. }
  153. }
  154. impl std::fmt::Display for SimpleNT {
  155. fn fmt(&self, w: &mut Formatter) -> fmt::Result {
  156. write!(w, "${}:{}", self.id, self.spec)
  157. }
  158. }
  159. fn write_space_separated<T:fmt::Display>(w: &mut Formatter,
  160. ts: &[T]) -> fmt::Result {
  161. let mut wrote_one = false;
  162. for t in ts {
  163. if wrote_one {
  164. try!(write!(w, " "));
  165. }
  166. try!(write!(w, "{}", t));
  167. wrote_one = true;
  168. }
  169. Ok(())
  170. }
  171.  
  172. impl std::fmt::Display for ComplexNT {
  173. fn fmt(&self, w: &mut Formatter) -> fmt::Result {
  174. try!(write!(w, "$("));
  175. try!(write_space_separated(w, &self.tokens));
  176. try!(write!(w, ")"));
  177. if let &Some(ref t) = &self.delim {
  178. try!(write!(w, "{}", *t));
  179. }
  180. let rep = match self.rep {
  181. Repeat::ZeroOrMore => "*",
  182. Repeat::OneOrMore => "+",
  183. };
  184. write!(w, "{}", rep)
  185. }
  186. }
  187. impl std::fmt::Display for NonTerm {
  188. fn fmt(&self, w: &mut Formatter) -> fmt::Result {
  189. match *self {
  190. NonTerm::Simple(ref nt) => write!(w, "{}", nt),
  191. NonTerm::Complex(ref nt) => write!(w, "{}", *nt),
  192. }
  193. }
  194. }
  195. impl std::fmt::Display for Token {
  196. fn fmt(&self, w: &mut Formatter) -> fmt::Result {
  197. match *self {
  198. Token::T(ref t) => write!(w, "{}", t),
  199. Token::NT(ref nt) => write!(w, "{}", nt),
  200. }
  201. }
  202. }
  203.  
  204. impl std::fmt::Display for TokenTree {
  205. fn fmt(&self, w: &mut Formatter) -> fmt::Result {
  206. match *self {
  207. TokenTree::Token(ref t) => write!(w, "{}", t),
  208. TokenTree::Group(Grouping::Parens, ref ts) => {
  209. try!(write!(w, "("));
  210. try!(write_space_separated(w, &ts[..]));
  211. write!(w, ")")
  212. }
  213. TokenTree::Group(Grouping::Brackets, ref ts) => {
  214. try!(write!(w, "["));
  215. try!(write_space_separated(w, &ts[..]));
  216. write!(w, "]")
  217. }
  218. TokenTree::Group(Grouping::Braces, ref ts) => {
  219. try!(write!(w, "{{"));
  220. try!(write_space_separated(w, &ts[..]));
  221. write!(w, "}}")
  222. }
  223. }
  224. }
  225. }
  226.  
  227.  
  228. fn main() {
  229. let ex1 = RepeatWith(vec![&"start" as &ToToken,
  230. &SimpleNT("foo", expr),
  231. &"end"].into_iter(), ",");
  232. let ex2 = TokenTree::Group(Grouping::Brackets,
  233. vec![ex1.to_tokentree(), ex1.to_tokentree()]);
  234. println!("Hello world! {}", ex1);
  235. println!("Hello world! {}", ex2);
  236. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement