Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #![allow(non_camel_case_types, dead_code, non_snake_case, unused_variables)]
- use std::borrow::{Cow, IntoCow};
- use std::fmt::{self, Formatter};
- use std::ascii::AsciiExt;
- use self::FragmentSpecifier::*;
- fn check_terminal(s: &str) {
- assert!(s.is_ascii());
- assert!(s.len() > 0);
- for c in s.chars() {
- assert!(!c.is_whitespace());
- }
- }
- fn check_ident(s: &str) {
- check_terminal(s);
- let first = s.chars().next().unwrap();
- assert!('a' <= first && first <= 'z' ||
- 'A' <= first && first <= 'Z' ||
- '_' == first);
- }
- #[derive(Clone)]
- struct Terminal { s: Cow<'static, str> }
- fn Terminal<S:IntoCow<'static, str>>(s: S) -> Terminal {
- let s = s.into_cow();
- check_terminal(&s);
- Terminal { s: s }
- }
- #[derive(Clone)]
- struct Ident { s: Cow<'static, str> }
- fn Ident<S:IntoCow<'static, str>>(s: S) -> Ident {
- let s = s.into_cow();
- check_ident(&s);
- Ident { s: s }
- }
- #[derive(Clone)]
- enum Token { T(Terminal), NT(NonTerm), }
- trait IntoToken: Sized { fn into_token(self) -> Token; }
- trait ToToken { fn to_token(&self) -> Token; }
- impl ToToken for &'static str {
- fn to_token(&self) -> Token { self.into_token() }
- }
- impl IntoToken for Token { fn into_token(self) -> Token { self } }
- impl IntoToken for &'static str {
- fn into_token(self) -> Token { Token::T(Terminal(self)) }
- }
- impl IntoToken for String {
- fn into_token(self) -> Token { Token::T(Terminal(self)) }
- }
- impl IntoToken for Ident {
- fn into_token(self) -> Token { Token::T(Terminal(self.s)) }
- }
- impl ToToken for Ident {
- fn to_token(&self) -> Token { Token::T(Terminal(self.s.clone())) }
- }
- impl IntoToken for Terminal {
- fn into_token(self) -> Token { Token::T(self) }
- }
- impl ToToken for Terminal {
- fn to_token(&self) -> Token { Token::T(Terminal(self.s.clone())) }
- }
- impl IntoToken for NonTerm {
- fn into_token(self) -> Token { Token::NT(self) }
- }
- impl ToToken for SimpleNT {
- fn to_token(&self) -> Token { Token::NT(NonTerm::Simple(self.clone())) }
- }
- impl ToToken for ComplexNT {
- fn to_token(&self) -> Token {
- Token::NT(NonTerm::Complex(Box::new(self.clone())))
- }
- }
- #[derive(Clone)]
- enum NonTerm { Simple(SimpleNT), Complex(Box<ComplexNT>), }
- #[derive(Clone)]
- struct SimpleNT { id: Ident, spec: FragmentSpecifier }
- fn SimpleNT<S:IntoCow<'static, str>>(id: S, spec: FragmentSpecifier) -> SimpleNT {
- SimpleNT { id: Ident(id), spec: spec }
- }
- #[derive(Clone)]
- struct ComplexNT { tokens: Vec<Token>, delim: Option<Token>, rep: Repeat }
- fn ComplexNT<'a, I:Iterator<Item=&'a ToToken>>(toks: I, delim: Option<Token>, rep: Repeat) -> ComplexNT{
- ComplexNT {
- tokens: toks.map(|x|x.to_token()).collect(),
- delim: delim,
- rep: rep
- }
- }
- fn RepeatWith<'a, I:Iterator<Item=&'a ToToken>, D:IntoToken>(toks: I, delim: D) -> ComplexNT {
- ComplexNT(toks, Some(delim.into_token()), Repeat::ZeroOrMore)
- }
- fn RepeatWithPlus<D:IntoToken>(toks: Vec<&ToToken>, delim: D) -> ComplexNT {
- ComplexNT(toks.into_iter(), Some(delim.into_token()), Repeat::OneOrMore)
- }
- fn Repeat(toks: Vec<&ToToken>) -> ComplexNT {
- ComplexNT(toks.into_iter(), None, Repeat::ZeroOrMore)
- }
- fn RepeatPlus(toks: Vec<&ToToken>) -> ComplexNT {
- ComplexNT(toks.into_iter(), None, Repeat::OneOrMore)
- }
- #[derive(Clone)]
- enum Repeat { ZeroOrMore, OneOrMore }
- #[derive(Clone)]
- enum FragmentSpecifier {
- pat, expr, ty, stmt, path, block, ident, tt, item, meta
- }
- #[derive(Clone)]
- enum TokenTree {
- Token(Token),
- Group(Grouping, Vec<TokenTree>),
- }
- #[derive(Clone)]
- enum Grouping { Parens, Brackets, Braces }
- trait ToTokenTree { fn to_tokentree(&self) -> TokenTree; }
- trait IntoTokenTree { fn into_tokentree(self) -> TokenTree; }
- impl<T:ToToken> ToTokenTree for T {
- fn to_tokentree(&self) -> TokenTree {
- TokenTree::Token(self.to_token().clone())
- }
- }
- impl std::fmt::Display for Terminal {
- fn fmt(&self, w: &mut Formatter) -> fmt::Result { write!(w, "{}", self.s) }
- }
- impl std::fmt::Display for Ident {
- fn fmt(&self, w: &mut Formatter) -> fmt::Result { write!(w, "{}", self.s) }
- }
- impl std::fmt::Display for FragmentSpecifier {
- fn fmt(&self, w: &mut Formatter) -> fmt::Result {
- let name = match *self {
- FragmentSpecifier::pat => "pat",
- FragmentSpecifier::expr => "expr",
- FragmentSpecifier::ty => "ty",
- FragmentSpecifier::stmt => "stmt",
- FragmentSpecifier::path => "path",
- FragmentSpecifier::block => "block",
- FragmentSpecifier::ident => "ident",
- FragmentSpecifier::tt => "tt",
- FragmentSpecifier::item => "item",
- FragmentSpecifier::meta => "meta",
- };
- write!(w, "{}", name)
- }
- }
- impl std::fmt::Display for SimpleNT {
- fn fmt(&self, w: &mut Formatter) -> fmt::Result {
- write!(w, "${}:{}", self.id, self.spec)
- }
- }
- fn write_space_separated<T:fmt::Display>(w: &mut Formatter,
- ts: &[T]) -> fmt::Result {
- let mut wrote_one = false;
- for t in ts {
- if wrote_one {
- try!(write!(w, " "));
- }
- try!(write!(w, "{}", t));
- wrote_one = true;
- }
- Ok(())
- }
- impl std::fmt::Display for ComplexNT {
- fn fmt(&self, w: &mut Formatter) -> fmt::Result {
- try!(write!(w, "$("));
- try!(write_space_separated(w, &self.tokens));
- try!(write!(w, ")"));
- if let &Some(ref t) = &self.delim {
- try!(write!(w, "{}", *t));
- }
- let rep = match self.rep {
- Repeat::ZeroOrMore => "*",
- Repeat::OneOrMore => "+",
- };
- write!(w, "{}", rep)
- }
- }
- impl std::fmt::Display for NonTerm {
- fn fmt(&self, w: &mut Formatter) -> fmt::Result {
- match *self {
- NonTerm::Simple(ref nt) => write!(w, "{}", nt),
- NonTerm::Complex(ref nt) => write!(w, "{}", *nt),
- }
- }
- }
- impl std::fmt::Display for Token {
- fn fmt(&self, w: &mut Formatter) -> fmt::Result {
- match *self {
- Token::T(ref t) => write!(w, "{}", t),
- Token::NT(ref nt) => write!(w, "{}", nt),
- }
- }
- }
- impl std::fmt::Display for TokenTree {
- fn fmt(&self, w: &mut Formatter) -> fmt::Result {
- match *self {
- TokenTree::Token(ref t) => write!(w, "{}", t),
- TokenTree::Group(Grouping::Parens, ref ts) => {
- try!(write!(w, "("));
- try!(write_space_separated(w, &ts[..]));
- write!(w, ")")
- }
- TokenTree::Group(Grouping::Brackets, ref ts) => {
- try!(write!(w, "["));
- try!(write_space_separated(w, &ts[..]));
- write!(w, "]")
- }
- TokenTree::Group(Grouping::Braces, ref ts) => {
- try!(write!(w, "{{"));
- try!(write_space_separated(w, &ts[..]));
- write!(w, "}}")
- }
- }
- }
- }
- fn main() {
- let ex1 = RepeatWith(vec![&"start" as &ToToken,
- &SimpleNT("foo", expr),
- &"end"].into_iter(), ",");
- let ex2 = TokenTree::Group(Grouping::Brackets,
- vec![ex1.to_tokentree(), ex1.to_tokentree()]);
- println!("Hello world! {}", ex1);
- println!("Hello world! {}", ex2);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement