unrest_tmp_syn/
lit.rs

1use std::fmt;
2use std::hash::{Hash, Hasher};
3
4use proc_macro2::{self, Literal, TokenNode, Term};
5
6use {Span, TokenTree};
7
8#[derive(Clone)]
9pub struct Lit {
10    pub value: LitKind,
11    pub span: Span,
12}
13
14#[derive(Clone)]
15pub enum LitKind {
16    Bool(bool),
17    Other(Literal),
18}
19
20impl Lit {
21    pub fn into_token_tree(self) -> TokenTree {
22        let kind = match self.value {
23            LitKind::Bool(true) => TokenNode::Term(Term::intern("true")),
24            LitKind::Bool(false) => TokenNode::Term(Term::intern("false")),
25            LitKind::Other(l) => TokenNode::Literal(l),
26        };
27        TokenTree(proc_macro2::TokenTree {
28            span: self.span.0,
29            kind: kind,
30        })
31    }
32}
33
34impl fmt::Display for Lit {
35    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
36        fmt::Display::fmt(&self.value, f)
37    }
38}
39
40impl fmt::Debug for Lit {
41    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
42        fmt::Display::fmt(&self.value, f)
43    }
44}
45
46impl PartialEq for Lit {
47    fn eq(&self, other: &Lit) -> bool {
48        self.value == other.value
49    }
50}
51
52impl Eq for Lit {}
53
54impl Hash for Lit {
55    fn hash<H: Hasher>(&self, hasher: &mut H) {
56        self.value.hash(hasher)
57    }
58}
59
60impl fmt::Display for LitKind {
61    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
62        match *self {
63            LitKind::Bool(b) => b.fmt(f),
64            LitKind::Other(ref l) => l.fmt(f),
65        }
66    }
67}
68
69impl fmt::Debug for LitKind {
70    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
71        match *self {
72            LitKind::Bool(b) => b.fmt(f),
73            LitKind::Other(ref l) => fmt::Display::fmt(l, f),
74        }
75    }
76}
77
78impl PartialEq for LitKind {
79    fn eq(&self, other: &LitKind) -> bool {
80        match (self, other) {
81            (&LitKind::Bool(b1), &LitKind::Bool(b2)) => b1 == b2,
82            (&LitKind::Other(ref l1), &LitKind::Other(ref l2)) => {
83                l1.to_string() == l2.to_string()
84            }
85            _ => false,
86        }
87    }
88}
89
90impl Eq for LitKind {}
91
92impl Hash for LitKind {
93    fn hash<H: Hasher>(&self, hasher: &mut H) {
94        match *self {
95            LitKind::Bool(b) => (0u8, b).hash(hasher),
96            LitKind::Other(ref l) => (1u8, l.to_string()).hash(hasher),
97        }
98    }
99}
100
101#[cfg(feature = "parsing")]
102pub mod parsing {
103    use super::*;
104    use synom::{Synom, PResult, Cursor, parse_error};
105
106    impl Synom for Lit {
107        fn parse(input: Cursor) -> PResult<Self> {
108            match input.literal() {
109                Some((rest, span, lit)) => {
110                    Ok((rest, Lit {
111                        span: Span(span),
112                        value: LitKind::Other(lit)
113                    }))
114                }
115                _ => match input.word() {
116                    Some((rest, span, sym)) => {
117                        let kind = if sym.as_str() == "true" {
118                            LitKind::Bool(true)
119                        } else if sym.as_str() == "false" {
120                            LitKind::Bool(false)
121                        } else {
122                            return parse_error();
123                        };
124
125                        Ok((rest, Lit {
126                            span: Span(span),
127                            value: kind
128                        }))
129                    }
130                    _ => parse_error(),
131                }
132            }
133        }
134    }
135}
136
137#[cfg(feature = "printing")]
138mod printing {
139    use super::*;
140    use quote::{Tokens, ToTokens};
141
142    impl ToTokens for Lit {
143        fn to_tokens(&self, tokens: &mut Tokens) {
144            self.clone().into_token_tree().to_tokens(tokens)
145        }
146    }
147}