Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 1 | use std::fmt; |
| 2 | use std::hash::{Hash, Hasher}; |
| 3 | |
| 4 | use proc_macro2::{self, Literal, TokenKind}; |
| 5 | |
| 6 | use {Span, TokenTree}; |
| 7 | |
| 8 | #[derive(Clone)] |
| 9 | pub struct Lit { |
| 10 | pub value: LitKind, |
| 11 | pub span: Span, |
| 12 | } |
| 13 | |
| 14 | #[derive(Clone)] |
| 15 | pub enum LitKind { |
| 16 | Bool(bool), |
| 17 | Other(Literal), |
| 18 | } |
| 19 | |
| 20 | impl 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 Crichton | 62a0a59 | 2017-05-22 13:58:53 -0700 | [diff] [blame] | 31 | } |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 32 | } |
| 33 | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 34 | impl fmt::Display for Lit { |
| 35 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| 36 | fmt::Display::fmt(&self.value, f) |
Alex Crichton | 62a0a59 | 2017-05-22 13:58:53 -0700 | [diff] [blame] | 37 | } |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 38 | } |
| 39 | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 40 | impl fmt::Debug for Lit { |
| 41 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| 42 | fmt::Display::fmt(&self.value, f) |
Pascal Hertleif | 36342c5 | 2016-10-19 10:31:42 +0200 | [diff] [blame] | 43 | } |
| 44 | } |
| 45 | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 46 | impl PartialEq for Lit { |
| 47 | fn eq(&self, other: &Lit) -> bool { |
| 48 | self.value == other.value |
Pascal Hertleif | 36342c5 | 2016-10-19 10:31:42 +0200 | [diff] [blame] | 49 | } |
| 50 | } |
| 51 | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 52 | impl Eq for Lit {} |
| 53 | |
| 54 | impl Hash for Lit { |
| 55 | fn hash<H: Hasher>(&self, hasher: &mut H) { |
| 56 | self.value.hash(hasher) |
Pascal Hertleif | 36342c5 | 2016-10-19 10:31:42 +0200 | [diff] [blame] | 57 | } |
| 58 | } |
| 59 | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 60 | impl 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 Hertleif | 36342c5 | 2016-10-19 10:31:42 +0200 | [diff] [blame] | 66 | } |
| 67 | } |
| 68 | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 69 | impl 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 Hertleif | 36342c5 | 2016-10-19 10:31:42 +0200 | [diff] [blame] | 75 | } |
| 76 | } |
| 77 | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 78 | impl 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 Hertleif | 36342c5 | 2016-10-19 10:31:42 +0200 | [diff] [blame] | 84 | } |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 85 | _ => false, |
| 86 | } |
Alex Crichton | 2e0229c | 2017-05-23 09:34:50 -0700 | [diff] [blame] | 87 | } |
David Tolnay | 5fe14fc | 2017-01-27 16:22:08 -0800 | [diff] [blame] | 88 | } |
| 89 | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 90 | impl Eq for LitKind {} |
David Tolnay | 5fe14fc | 2017-01-27 16:22:08 -0800 | [diff] [blame] | 91 | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 92 | impl 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 Crichton | 2e0229c | 2017-05-23 09:34:50 -0700 | [diff] [blame] | 98 | } |
David Tolnay | 5fe14fc | 2017-01-27 16:22:08 -0800 | [diff] [blame] | 99 | } |
| 100 | |
| 101 | #[cfg(feature = "parsing")] |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 102 | pub mod parsing { |
| 103 | use super::*; |
David Tolnay | fe373a3 | 2016-10-26 23:51:19 -0700 | [diff] [blame] | 104 | use escape::{cooked_byte, cooked_byte_string, cooked_char, cooked_string, raw_string}; |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 105 | use proc_macro2::Literal; |
David Tolnay | 5fe14fc | 2017-01-27 16:22:08 -0800 | [diff] [blame] | 106 | use synom::IResult; |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 107 | use synom::space::skip_whitespace; |
David Tolnay | 4f5f60f | 2016-10-24 00:52:58 -0700 | [diff] [blame] | 108 | use unicode_xid::UnicodeXID; |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 109 | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 110 | fn l<T: Into<Literal>>(t: T) -> Lit { |
| 111 | Lit { |
| 112 | value: LitKind::Other(t.into()), |
| 113 | span: Default::default(), |
| 114 | } |
| 115 | } |
| 116 | |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 117 | named!(pub lit -> Lit, alt!( |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 118 | string |
David Tolnay | 56d6213 | 2016-10-01 16:14:54 -0700 | [diff] [blame] | 119 | | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 120 | byte_string |
David Tolnay | 615cf6a | 2016-10-08 23:07:02 -0700 | [diff] [blame] | 121 | | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 122 | byte |
David Tolnay | 615cf6a | 2016-10-08 23:07:02 -0700 | [diff] [blame] | 123 | | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 124 | character |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 125 | | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 126 | float |
David Tolnay | 4f5f60f | 2016-10-24 00:52:58 -0700 | [diff] [blame] | 127 | | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 128 | int |
David Tolnay | 759d2ff | 2016-10-01 16:18:15 -0700 | [diff] [blame] | 129 | | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 130 | boolean |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 131 | )); |
| 132 | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 133 | named!(pub string -> Lit, alt!( |
| 134 | quoted_string => { |s: String| l(&s[..]) } |
David Tolnay | 210884d | 2016-10-01 08:18:42 -0700 | [diff] [blame] | 135 | | |
| 136 | preceded!( |
| 137 | punct!("r"), |
| 138 | raw_string |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 139 | ) => { |(s, n): (String, _)| l(Literal::raw_string(&s[..], n)) } |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 140 | )); |
| 141 | |
David Tolnay | 4260229 | 2016-10-01 22:25:45 -0700 | [diff] [blame] | 142 | named!(pub quoted_string -> String, delimited!( |
| 143 | punct!("\""), |
| 144 | cooked_string, |
| 145 | tag!("\"") |
| 146 | )); |
| 147 | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 148 | named!(pub byte_string -> Lit, alt!( |
David Tolnay | 56d6213 | 2016-10-01 16:14:54 -0700 | [diff] [blame] | 149 | delimited!( |
| 150 | punct!("b\""), |
David Tolnay | a73e0f0 | 2016-10-26 23:25:49 -0700 | [diff] [blame] | 151 | cooked_byte_string, |
David Tolnay | 56d6213 | 2016-10-01 16:14:54 -0700 | [diff] [blame] | 152 | tag!("\"") |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 153 | ) => { |vec: Vec<u8>| l(Literal::byte_string(&vec)) } |
David Tolnay | 56d6213 | 2016-10-01 16:14:54 -0700 | [diff] [blame] | 154 | | |
| 155 | preceded!( |
| 156 | punct!("br"), |
| 157 | raw_string |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 158 | ) => { |(s, n): (String, _)| l(Literal::raw_byte_string(&s, n)) } |
David Tolnay | 56d6213 | 2016-10-01 16:14:54 -0700 | [diff] [blame] | 159 | )); |
| 160 | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 161 | named!(pub byte -> Lit, do_parse!( |
David Tolnay | 615cf6a | 2016-10-08 23:07:02 -0700 | [diff] [blame] | 162 | punct!("b") >> |
| 163 | tag!("'") >> |
David Tolnay | fe373a3 | 2016-10-26 23:51:19 -0700 | [diff] [blame] | 164 | b: cooked_byte >> |
David Tolnay | 615cf6a | 2016-10-08 23:07:02 -0700 | [diff] [blame] | 165 | tag!("'") >> |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 166 | (l(Literal::byte_char(b))) |
David Tolnay | 615cf6a | 2016-10-08 23:07:02 -0700 | [diff] [blame] | 167 | )); |
| 168 | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 169 | named!(pub character -> Lit, do_parse!( |
David Tolnay | 615cf6a | 2016-10-08 23:07:02 -0700 | [diff] [blame] | 170 | punct!("'") >> |
| 171 | ch: cooked_char >> |
| 172 | tag!("'") >> |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 173 | (l(ch)) |
David Tolnay | 615cf6a | 2016-10-08 23:07:02 -0700 | [diff] [blame] | 174 | )); |
| 175 | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 176 | named!(pub float -> Lit, do_parse!( |
David Tolnay | 5fe14fc | 2017-01-27 16:22:08 -0800 | [diff] [blame] | 177 | value: float_string >> |
| 178 | suffix: alt!( |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 179 | tag!("f32") |
David Tolnay | 4f5f60f | 2016-10-24 00:52:58 -0700 | [diff] [blame] | 180 | | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 181 | tag!("f64") |
David Tolnay | 4f5f60f | 2016-10-24 00:52:58 -0700 | [diff] [blame] | 182 | | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 183 | epsilon!() => { |_| "" } |
David Tolnay | 5fe14fc | 2017-01-27 16:22:08 -0800 | [diff] [blame] | 184 | ) >> |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 185 | (l(Literal::float(&format!("{}{}", value, suffix)))) |
David Tolnay | 4f5f60f | 2016-10-24 00:52:58 -0700 | [diff] [blame] | 186 | )); |
| 187 | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 188 | named!(pub int -> Lit, do_parse!( |
David Tolnay | 5fe14fc | 2017-01-27 16:22:08 -0800 | [diff] [blame] | 189 | value: digits >> |
| 190 | suffix: alt!( |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 191 | tag!("isize") |
David Tolnay | de20622 | 2016-09-30 11:47:01 -0700 | [diff] [blame] | 192 | | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 193 | tag!("i8") |
David Tolnay | de20622 | 2016-09-30 11:47:01 -0700 | [diff] [blame] | 194 | | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 195 | tag!("i16") |
David Tolnay | de20622 | 2016-09-30 11:47:01 -0700 | [diff] [blame] | 196 | | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 197 | tag!("i32") |
David Tolnay | de20622 | 2016-09-30 11:47:01 -0700 | [diff] [blame] | 198 | | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 199 | tag!("i64") |
David Tolnay | de20622 | 2016-09-30 11:47:01 -0700 | [diff] [blame] | 200 | | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 201 | tag!("usize") |
David Tolnay | de20622 | 2016-09-30 11:47:01 -0700 | [diff] [blame] | 202 | | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 203 | tag!("u8") |
David Tolnay | de20622 | 2016-09-30 11:47:01 -0700 | [diff] [blame] | 204 | | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 205 | tag!("u16") |
David Tolnay | de20622 | 2016-09-30 11:47:01 -0700 | [diff] [blame] | 206 | | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 207 | tag!("u32") |
David Tolnay | de20622 | 2016-09-30 11:47:01 -0700 | [diff] [blame] | 208 | | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 209 | tag!("u64") |
David Tolnay | de20622 | 2016-09-30 11:47:01 -0700 | [diff] [blame] | 210 | | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 211 | epsilon!() => { |_| "" } |
David Tolnay | 5fe14fc | 2017-01-27 16:22:08 -0800 | [diff] [blame] | 212 | ) >> |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 213 | (l(Literal::integer(&format!("{}{}", value, suffix)))) |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 214 | )); |
| 215 | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 216 | named!(pub boolean -> Lit, alt!( |
| 217 | keyword!("true") => { |_| Lit { |
| 218 | span: Span::default(), |
| 219 | value: LitKind::Bool(true), |
| 220 | } } |
David Tolnay | 3ce49d0 | 2016-10-23 22:29:19 -0700 | [diff] [blame] | 221 | | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 222 | keyword!("false") => { |_| Lit { |
| 223 | span: Span::default(), |
| 224 | value: LitKind::Bool(false), |
| 225 | } } |
David Tolnay | 3ce49d0 | 2016-10-23 22:29:19 -0700 | [diff] [blame] | 226 | )); |
| 227 | |
David Tolnay | def6637 | 2016-10-24 21:51:32 -0700 | [diff] [blame] | 228 | fn float_string(mut input: &str) -> IResult<&str, String> { |
| 229 | input = skip_whitespace(input); |
| 230 | |
David Tolnay | 4f5f60f | 2016-10-24 00:52:58 -0700 | [diff] [blame] | 231 | let mut chars = input.chars().peekable(); |
| 232 | match chars.next() { |
| 233 | Some(ch) if ch >= '0' && ch <= '9' => {} |
| 234 | _ => return IResult::Error, |
| 235 | } |
| 236 | |
| 237 | let mut len = 1; |
| 238 | let mut has_dot = false; |
| 239 | let mut has_exp = false; |
| 240 | while let Some(&ch) = chars.peek() { |
| 241 | match ch { |
| 242 | '0'...'9' | '_' => { |
| 243 | chars.next(); |
| 244 | len += 1; |
| 245 | } |
| 246 | '.' => { |
| 247 | if has_dot { |
| 248 | break; |
| 249 | } |
| 250 | chars.next(); |
| 251 | if chars.peek() |
David Tolnay | 05120ef | 2017-03-12 18:29:26 -0700 | [diff] [blame] | 252 | .map(|&ch| ch == '.' || UnicodeXID::is_xid_start(ch)) |
| 253 | .unwrap_or(false) { |
David Tolnay | 4f5f60f | 2016-10-24 00:52:58 -0700 | [diff] [blame] | 254 | return IResult::Error; |
| 255 | } |
| 256 | len += 1; |
| 257 | has_dot = true; |
| 258 | } |
| 259 | 'e' | 'E' => { |
| 260 | chars.next(); |
| 261 | len += 1; |
| 262 | has_exp = true; |
| 263 | break; |
| 264 | } |
| 265 | _ => break, |
| 266 | } |
| 267 | } |
| 268 | |
| 269 | let rest = &input[len..]; |
| 270 | if !(has_dot || has_exp || rest.starts_with("f32") || rest.starts_with("f64")) { |
| 271 | return IResult::Error; |
| 272 | } |
| 273 | |
| 274 | if has_exp { |
| 275 | let mut has_exp_value = false; |
| 276 | while let Some(&ch) = chars.peek() { |
| 277 | match ch { |
| 278 | '+' | '-' => { |
| 279 | if has_exp_value { |
| 280 | break; |
| 281 | } |
| 282 | chars.next(); |
| 283 | len += 1; |
| 284 | } |
| 285 | '0'...'9' => { |
| 286 | chars.next(); |
| 287 | len += 1; |
| 288 | has_exp_value = true; |
| 289 | } |
| 290 | '_' => { |
| 291 | chars.next(); |
| 292 | len += 1; |
| 293 | } |
| 294 | _ => break, |
| 295 | } |
| 296 | } |
| 297 | if !has_exp_value { |
| 298 | return IResult::Error; |
| 299 | } |
| 300 | } |
| 301 | |
David Tolnay | c7b636a | 2016-10-24 13:01:08 -0700 | [diff] [blame] | 302 | IResult::Done(&input[len..], input[..len].replace("_", "")) |
David Tolnay | 4f5f60f | 2016-10-24 00:52:58 -0700 | [diff] [blame] | 303 | } |
| 304 | |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 305 | pub fn digits(mut input: &str) -> IResult<&str, &str> { |
David Tolnay | def6637 | 2016-10-24 21:51:32 -0700 | [diff] [blame] | 306 | input = skip_whitespace(input); |
| 307 | |
David Tolnay | 8a19e6d | 2016-10-24 01:23:40 -0700 | [diff] [blame] | 308 | let base = if input.starts_with("0x") { |
David Tolnay | 8a19e6d | 2016-10-24 01:23:40 -0700 | [diff] [blame] | 309 | 16 |
| 310 | } else if input.starts_with("0o") { |
David Tolnay | 8a19e6d | 2016-10-24 01:23:40 -0700 | [diff] [blame] | 311 | 8 |
| 312 | } else if input.starts_with("0b") { |
David Tolnay | 8a19e6d | 2016-10-24 01:23:40 -0700 | [diff] [blame] | 313 | 2 |
| 314 | } else { |
| 315 | 10 |
| 316 | }; |
| 317 | |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 318 | let mut value = 0u64; |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 319 | let mut len = if base == 10 {0} else {2}; |
David Tolnay | 24b5ff7 | 2016-10-24 01:05:05 -0700 | [diff] [blame] | 320 | let mut empty = true; |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 321 | for b in input[len..].bytes() { |
David Tolnay | 8a19e6d | 2016-10-24 01:23:40 -0700 | [diff] [blame] | 322 | let digit = match b { |
| 323 | b'0'...b'9' => (b - b'0') as u64, |
| 324 | b'a'...b'f' => 10 + (b - b'a') as u64, |
| 325 | b'A'...b'F' => 10 + (b - b'A') as u64, |
David Tolnay | 24b5ff7 | 2016-10-24 01:05:05 -0700 | [diff] [blame] | 326 | b'_' => { |
David Tolnay | c814a76 | 2016-10-27 23:11:28 -0700 | [diff] [blame] | 327 | if empty && base == 10 { |
David Tolnay | 24b5ff7 | 2016-10-24 01:05:05 -0700 | [diff] [blame] | 328 | return IResult::Error; |
| 329 | } |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 330 | len += 1; |
David Tolnay | 8a19e6d | 2016-10-24 01:23:40 -0700 | [diff] [blame] | 331 | continue; |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 332 | } |
David Tolnay | fa0edf2 | 2016-09-23 22:58:24 -0700 | [diff] [blame] | 333 | _ => break, |
David Tolnay | 8a19e6d | 2016-10-24 01:23:40 -0700 | [diff] [blame] | 334 | }; |
| 335 | if digit >= base { |
| 336 | return IResult::Error; |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 337 | } |
David Tolnay | 8a19e6d | 2016-10-24 01:23:40 -0700 | [diff] [blame] | 338 | value = match value.checked_mul(base) { |
| 339 | Some(value) => value, |
| 340 | None => return IResult::Error, |
| 341 | }; |
| 342 | value = match value.checked_add(digit) { |
| 343 | Some(value) => value, |
| 344 | None => return IResult::Error, |
| 345 | }; |
| 346 | len += 1; |
| 347 | empty = false; |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 348 | } |
David Tolnay | 24b5ff7 | 2016-10-24 01:05:05 -0700 | [diff] [blame] | 349 | if empty { |
David Tolnay | fa0edf2 | 2016-09-23 22:58:24 -0700 | [diff] [blame] | 350 | IResult::Error |
David Tolnay | 24b5ff7 | 2016-10-24 01:05:05 -0700 | [diff] [blame] | 351 | } else { |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 352 | IResult::Done(&input[len..], &input[..len]) |
David Tolnay | fa0edf2 | 2016-09-23 22:58:24 -0700 | [diff] [blame] | 353 | } |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 354 | } |
| 355 | } |
| 356 | |
| 357 | #[cfg(feature = "printing")] |
| 358 | mod printing { |
| 359 | use super::*; |
| 360 | use quote::{Tokens, ToTokens}; |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 361 | |
| 362 | use proc_macro2::{TokenTree, TokenKind}; |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 363 | |
| 364 | impl ToTokens for Lit { |
| 365 | fn to_tokens(&self, tokens: &mut Tokens) { |
Alex Crichton | ccbb45d | 2017-05-23 10:58:24 -0700 | [diff] [blame^] | 366 | let kind = match self.value { |
| 367 | LitKind::Bool(true) => TokenKind::Word("true".into()), |
| 368 | LitKind::Bool(false) => TokenKind::Word("false".into()), |
| 369 | LitKind::Other(ref l) => TokenKind::Literal(l.clone()), |
| 370 | }; |
| 371 | tokens.append(TokenTree { |
| 372 | span: self.span.0, |
| 373 | kind: kind, |
| 374 | }); |
David Tolnay | f17fd2f | 2016-10-07 23:38:08 -0700 | [diff] [blame] | 375 | } |
| 376 | } |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 377 | } |