blob: 659571eb9455c6d32a0e76878520dd1e5f16d2f0 [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> {
Michael Layzell589a8f42017-06-02 19:47:01 -0400108 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 }
David Tolnayfa0edf22016-09-23 22:58:24 -0700133 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700134 }
135}
136
137#[cfg(feature = "printing")]
138mod printing {
139 use super::*;
140 use quote::{Tokens, ToTokens};
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700141
142 use proc_macro2::{TokenTree, TokenKind};
David Tolnayf4bbbd92016-09-23 14:41:55 -0700143
144 impl ToTokens for Lit {
145 fn to_tokens(&self, tokens: &mut Tokens) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700146 let kind = match self.value {
147 LitKind::Bool(true) => TokenKind::Word("true".into()),
148 LitKind::Bool(false) => TokenKind::Word("false".into()),
149 LitKind::Other(ref l) => TokenKind::Literal(l.clone()),
150 };
151 tokens.append(TokenTree {
152 span: self.span.0,
153 kind: kind,
154 });
David Tolnayf17fd2f2016-10-07 23:38:08 -0700155 }
156 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700157}