blob: 9480563859a1f0f72dd5847e4bcbc084a4558582 [file] [log] [blame]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001use std::fmt;
2use std::hash::{Hash, Hasher};
3
David Tolnay9c76bcb2017-12-26 23:14:59 -05004use proc_macro2::{self, Span, Literal, TokenNode, TokenTree, Term};
Alex Crichtonccbb45d2017-05-23 10:58:24 -07005
6#[derive(Clone)]
7pub struct Lit {
8 pub value: LitKind,
9 pub span: Span,
10}
11
12#[derive(Clone)]
13pub enum LitKind {
14 Bool(bool),
15 Other(Literal),
16}
17
18impl Lit {
19 pub fn into_token_tree(self) -> TokenTree {
20 let kind = match self.value {
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -070021 LitKind::Bool(true) => TokenNode::Term(Term::intern("true")),
22 LitKind::Bool(false) => TokenNode::Term(Term::intern("false")),
23 LitKind::Other(l) => TokenNode::Literal(l),
Alex Crichtonccbb45d2017-05-23 10:58:24 -070024 };
David Tolnay9c76bcb2017-12-26 23:14:59 -050025 proc_macro2::TokenTree {
David Tolnay98942562017-12-26 21:24:35 -050026 span: self.span,
Alex Crichtonccbb45d2017-05-23 10:58:24 -070027 kind: kind,
David Tolnay9c76bcb2017-12-26 23:14:59 -050028 }
Alex Crichton62a0a592017-05-22 13:58:53 -070029 }
David Tolnayf4bbbd92016-09-23 14:41:55 -070030}
31
Alex Crichtonccbb45d2017-05-23 10:58:24 -070032impl fmt::Display for Lit {
33 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
34 fmt::Display::fmt(&self.value, f)
Alex Crichton62a0a592017-05-22 13:58:53 -070035 }
David Tolnayf4bbbd92016-09-23 14:41:55 -070036}
37
Alex Crichtonccbb45d2017-05-23 10:58:24 -070038impl fmt::Debug for Lit {
39 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
40 fmt::Display::fmt(&self.value, f)
Pascal Hertleif36342c52016-10-19 10:31:42 +020041 }
42}
43
Alex Crichtonccbb45d2017-05-23 10:58:24 -070044impl PartialEq for Lit {
45 fn eq(&self, other: &Lit) -> bool {
46 self.value == other.value
Pascal Hertleif36342c52016-10-19 10:31:42 +020047 }
48}
49
Alex Crichtonccbb45d2017-05-23 10:58:24 -070050impl Eq for Lit {}
51
52impl Hash for Lit {
53 fn hash<H: Hasher>(&self, hasher: &mut H) {
54 self.value.hash(hasher)
Pascal Hertleif36342c52016-10-19 10:31:42 +020055 }
56}
57
Alex Crichtonccbb45d2017-05-23 10:58:24 -070058impl fmt::Display for LitKind {
59 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
60 match *self {
61 LitKind::Bool(b) => b.fmt(f),
62 LitKind::Other(ref l) => l.fmt(f),
63 }
Pascal Hertleif36342c52016-10-19 10:31:42 +020064 }
65}
66
Alex Crichtonccbb45d2017-05-23 10:58:24 -070067impl fmt::Debug for LitKind {
68 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
69 match *self {
70 LitKind::Bool(b) => b.fmt(f),
71 LitKind::Other(ref l) => fmt::Display::fmt(l, f),
72 }
Pascal Hertleif36342c52016-10-19 10:31:42 +020073 }
74}
75
Alex Crichtonccbb45d2017-05-23 10:58:24 -070076impl PartialEq for LitKind {
77 fn eq(&self, other: &LitKind) -> bool {
78 match (self, other) {
79 (&LitKind::Bool(b1), &LitKind::Bool(b2)) => b1 == b2,
80 (&LitKind::Other(ref l1), &LitKind::Other(ref l2)) => {
81 l1.to_string() == l2.to_string()
Pascal Hertleif36342c52016-10-19 10:31:42 +020082 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -070083 _ => false,
84 }
Alex Crichton2e0229c2017-05-23 09:34:50 -070085 }
David Tolnay5fe14fc2017-01-27 16:22:08 -080086}
87
Alex Crichtonccbb45d2017-05-23 10:58:24 -070088impl Eq for LitKind {}
David Tolnay5fe14fc2017-01-27 16:22:08 -080089
Alex Crichtonccbb45d2017-05-23 10:58:24 -070090impl Hash for LitKind {
91 fn hash<H: Hasher>(&self, hasher: &mut H) {
92 match *self {
93 LitKind::Bool(b) => (0u8, b).hash(hasher),
94 LitKind::Other(ref l) => (1u8, l.to_string()).hash(hasher),
95 }
Alex Crichton2e0229c2017-05-23 09:34:50 -070096 }
David Tolnay5fe14fc2017-01-27 16:22:08 -080097}
98
99#[cfg(feature = "parsing")]
David Tolnayf4bbbd92016-09-23 14:41:55 -0700100pub mod parsing {
101 use super::*;
David Tolnayc5ab8c62017-12-26 16:43:39 -0500102 use synom::Synom;
103 use cursor::Cursor;
104 use {PResult, 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 {
David Tolnay98942562017-12-26 21:24:35 -0500111 span: span,
Michael Layzell589a8f42017-06-02 19:47:01 -0400112 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 {
David Tolnay98942562017-12-26 21:24:35 -0500126 span: span,
Michael Layzell589a8f42017-06-02 19:47:01 -0400127 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
David Tolnayf4bbbd92016-09-23 14:41:55 -0700142 impl ToTokens for Lit {
143 fn to_tokens(&self, tokens: &mut Tokens) {
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700144 self.clone().into_token_tree().to_tokens(tokens)
David Tolnayf17fd2f2016-10-07 23:38:08 -0700145 }
146 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700147}