blob: c9b422926f5009516cc206859f7b70cde759cc47 [file] [log] [blame]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001use std::fmt;
2use std::hash::{Hash, Hasher};
3
4use proc_macro2::{self, Literal, TokenKind};
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) => TokenKind::Word("true".into()),
24 LitKind::Bool(false) => TokenKind::Word("false".into()),
25 LitKind::Other(l) => TokenKind::Literal(l),
26 };
27 TokenTree(proc_macro2::TokenTree {
28 span: self.span.0,
29 kind: kind,
30 })
Alex Crichton62a0a592017-05-22 13:58:53 -070031 }
David Tolnayf4bbbd92016-09-23 14:41:55 -070032}
33
Alex Crichtonccbb45d2017-05-23 10:58:24 -070034impl fmt::Display for Lit {
35 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
36 fmt::Display::fmt(&self.value, f)
Alex Crichton62a0a592017-05-22 13:58:53 -070037 }
David Tolnayf4bbbd92016-09-23 14:41:55 -070038}
39
Alex Crichtonccbb45d2017-05-23 10:58:24 -070040impl fmt::Debug for Lit {
41 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
42 fmt::Display::fmt(&self.value, f)
Pascal Hertleif36342c52016-10-19 10:31:42 +020043 }
44}
45
Alex Crichtonccbb45d2017-05-23 10:58:24 -070046impl PartialEq for Lit {
47 fn eq(&self, other: &Lit) -> bool {
48 self.value == other.value
Pascal Hertleif36342c52016-10-19 10:31:42 +020049 }
50}
51
Alex Crichtonccbb45d2017-05-23 10:58:24 -070052impl Eq for Lit {}
53
54impl Hash for Lit {
55 fn hash<H: Hasher>(&self, hasher: &mut H) {
56 self.value.hash(hasher)
Pascal Hertleif36342c52016-10-19 10:31:42 +020057 }
58}
59
Alex Crichtonccbb45d2017-05-23 10:58:24 -070060impl 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 }
Pascal Hertleif36342c52016-10-19 10:31:42 +020066 }
67}
68
Alex Crichtonccbb45d2017-05-23 10:58:24 -070069impl 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 }
Pascal Hertleif36342c52016-10-19 10:31:42 +020075 }
76}
77
Alex Crichtonccbb45d2017-05-23 10:58:24 -070078impl 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()
Pascal Hertleif36342c52016-10-19 10:31:42 +020084 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -070085 _ => false,
86 }
Alex Crichton2e0229c2017-05-23 09:34:50 -070087 }
David Tolnay5fe14fc2017-01-27 16:22:08 -080088}
89
Alex Crichtonccbb45d2017-05-23 10:58:24 -070090impl Eq for LitKind {}
David Tolnay5fe14fc2017-01-27 16:22:08 -080091
Alex Crichtonccbb45d2017-05-23 10:58:24 -070092impl 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 }
Alex Crichton2e0229c2017-05-23 09:34:50 -070098 }
David Tolnay5fe14fc2017-01-27 16:22:08 -080099}
100
101#[cfg(feature = "parsing")]
David Tolnayf4bbbd92016-09-23 14:41:55 -0700102pub mod parsing {
103 use super::*;
Michael Layzell92639a52017-06-01 00:07:44 -0400104 use synom::{Synom, PResult, Cursor, parse_error};
David Tolnayf4bbbd92016-09-23 14:41:55 -0700105
Alex Crichton954046c2017-05-30 21:49:42 -0700106 impl Synom for Lit {
Michael Layzell92639a52017-06-01 00:07:44 -0400107 fn parse(input: Cursor) -> PResult<Self> {
Alex Crichton954046c2017-05-30 21:49:42 -0700108 let mut tokens = input.iter();
109 let token = match tokens.next() {
110 Some(token) => token,
Michael Layzell92639a52017-06-01 00:07:44 -0400111 None => return parse_error(),
David Tolnay8a19e6d2016-10-24 01:23:40 -0700112 };
Alex Crichton954046c2017-05-30 21:49:42 -0700113 let kind = match token.kind {
114 TokenKind::Literal(ref l) => LitKind::Other(l.clone()),
115 TokenKind::Word(ref s) if s.as_str() == "true" => LitKind::Bool(true),
116 TokenKind::Word(ref s) if s.as_str() == "false" => LitKind::Bool(false),
Michael Layzell92639a52017-06-01 00:07:44 -0400117 _ => return parse_error(),
David Tolnay8a19e6d2016-10-24 01:23:40 -0700118 };
Michael Layzell92639a52017-06-01 00:07:44 -0400119 Ok((tokens.as_slice(), Lit {
Alex Crichton954046c2017-05-30 21:49:42 -0700120 span: Span(token.span),
121 value: kind,
Michael Layzell92639a52017-06-01 00:07:44 -0400122 }))
David Tolnayfa0edf22016-09-23 22:58:24 -0700123 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700124 }
125}
126
127#[cfg(feature = "printing")]
128mod printing {
129 use super::*;
130 use quote::{Tokens, ToTokens};
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700131
132 use proc_macro2::{TokenTree, TokenKind};
David Tolnayf4bbbd92016-09-23 14:41:55 -0700133
134 impl ToTokens for Lit {
135 fn to_tokens(&self, tokens: &mut Tokens) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700136 let kind = match self.value {
137 LitKind::Bool(true) => TokenKind::Word("true".into()),
138 LitKind::Bool(false) => TokenKind::Word("false".into()),
139 LitKind::Other(ref l) => TokenKind::Literal(l.clone()),
140 };
141 tokens.append(TokenTree {
142 span: self.span.0,
143 kind: kind,
144 });
David Tolnayf17fd2f2016-10-07 23:38:08 -0700145 }
146 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700147}