blob: b7b1e3e7096214dd6c93f06e58a0fa3a5d83e31d [file] [log] [blame]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001use std::fmt;
2use std::hash::{Hash, Hasher};
3
David Tolnay51382052017-12-27 13:46:21 -05004use proc_macro2::{self, Literal, Span, Term, TokenNode, TokenTree};
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,
David Tolnay51382052017-12-27 13:46:21 -050080 (&LitKind::Other(ref l1), &LitKind::Other(ref l2)) => l1.to_string() == l2.to_string(),
Alex Crichtonccbb45d2017-05-23 10:58:24 -070081 _ => false,
82 }
Alex Crichton2e0229c2017-05-23 09:34:50 -070083 }
David Tolnay5fe14fc2017-01-27 16:22:08 -080084}
85
Alex Crichtonccbb45d2017-05-23 10:58:24 -070086impl Eq for LitKind {}
David Tolnay5fe14fc2017-01-27 16:22:08 -080087
Alex Crichtonccbb45d2017-05-23 10:58:24 -070088impl Hash for LitKind {
89 fn hash<H: Hasher>(&self, hasher: &mut H) {
90 match *self {
91 LitKind::Bool(b) => (0u8, b).hash(hasher),
92 LitKind::Other(ref l) => (1u8, l.to_string()).hash(hasher),
93 }
Alex Crichton2e0229c2017-05-23 09:34:50 -070094 }
David Tolnay5fe14fc2017-01-27 16:22:08 -080095}
96
97#[cfg(feature = "parsing")]
David Tolnayf4bbbd92016-09-23 14:41:55 -070098pub mod parsing {
99 use super::*;
David Tolnayc5ab8c62017-12-26 16:43:39 -0500100 use synom::Synom;
101 use cursor::Cursor;
David Tolnay203557a2017-12-27 23:59:33 -0500102 use parse_error;
103 use synom::PResult;
David Tolnayf4bbbd92016-09-23 14:41:55 -0700104
Alex Crichton954046c2017-05-30 21:49:42 -0700105 impl Synom for Lit {
Michael Layzell92639a52017-06-01 00:07:44 -0400106 fn parse(input: Cursor) -> PResult<Self> {
Michael Layzell589a8f42017-06-02 19:47:01 -0400107 match input.literal() {
David Tolnay51382052017-12-27 13:46:21 -0500108 Some((rest, span, lit)) => Ok((
109 rest,
110 Lit {
David Tolnay98942562017-12-26 21:24:35 -0500111 span: span,
David Tolnay51382052017-12-27 13:46:21 -0500112 value: LitKind::Other(lit),
113 },
114 )),
David Tolnay73c98de2017-12-31 15:56:56 -0500115 _ => match input.term() {
116 Some((rest, span, term)) => {
117 let kind = if term.as_str() == "true" {
Michael Layzell589a8f42017-06-02 19:47:01 -0400118 LitKind::Bool(true)
David Tolnay73c98de2017-12-31 15:56:56 -0500119 } else if term.as_str() == "false" {
Michael Layzell589a8f42017-06-02 19:47:01 -0400120 LitKind::Bool(false)
121 } else {
122 return parse_error();
123 };
124
David Tolnay51382052017-12-27 13:46:21 -0500125 Ok((
126 rest,
127 Lit {
128 span: span,
129 value: kind,
130 },
131 ))
Michael Layzell589a8f42017-06-02 19:47:01 -0400132 }
133 _ => parse_error(),
David Tolnay51382052017-12-27 13:46:21 -0500134 },
Michael Layzell589a8f42017-06-02 19:47:01 -0400135 }
David Tolnayfa0edf22016-09-23 22:58:24 -0700136 }
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800137
138 fn description() -> Option<&'static str> {
139 Some("literal")
140 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700141 }
142}
143
144#[cfg(feature = "printing")]
145mod printing {
146 use super::*;
David Tolnay51382052017-12-27 13:46:21 -0500147 use quote::{ToTokens, Tokens};
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700148
David Tolnayf4bbbd92016-09-23 14:41:55 -0700149 impl ToTokens for Lit {
150 fn to_tokens(&self, tokens: &mut Tokens) {
Alex Crichtonf9e8f1a2017-07-05 18:20:44 -0700151 self.clone().into_token_tree().to_tokens(tokens)
David Tolnayf17fd2f2016-10-07 23:38:08 -0700152 }
153 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700154}