Alex Crichton | 62a0a59 | 2017-05-22 13:58:53 -0700 | [diff] [blame] | 1 | ast_enum! { |
| 2 | /// Literal kind. |
| 3 | /// |
| 4 | /// E.g. `"foo"`, `42`, `12.34` or `bool` |
Alex Crichton | 2e0229c | 2017-05-23 09:34:50 -0700 | [diff] [blame^] | 5 | #[cfg_attr(not(feature = "clone-impls"), derive(Clone))] |
Alex Crichton | 62a0a59 | 2017-05-22 13:58:53 -0700 | [diff] [blame] | 6 | pub enum Lit { |
| 7 | /// A string literal (`"foo"`) |
| 8 | Str(String, StrStyle), |
| 9 | /// A byte string (`b"foo"`) |
| 10 | ByteStr(Vec<u8>, StrStyle), |
| 11 | /// A byte char (`b'f'`) |
| 12 | Byte(u8), |
| 13 | /// A character literal (`'a'`) |
| 14 | Char(char), |
| 15 | /// An integer literal (`1`) |
| 16 | Int(u64, IntTy), |
| 17 | /// A float literal (`1f64` or `1E10f64` or `1.0E10`) |
| 18 | Float(String, FloatTy), |
| 19 | /// A boolean literal |
| 20 | Bool(bool), |
| 21 | } |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 22 | } |
| 23 | |
Alex Crichton | 62a0a59 | 2017-05-22 13:58:53 -0700 | [diff] [blame] | 24 | ast_enum! { |
Alex Crichton | 2e0229c | 2017-05-23 09:34:50 -0700 | [diff] [blame^] | 25 | #[cfg_attr(not(feature = "clone-impls"), derive(Clone))] |
Alex Crichton | 62a0a59 | 2017-05-22 13:58:53 -0700 | [diff] [blame] | 26 | pub enum StrStyle { |
| 27 | /// A regular string, like `"foo"` |
| 28 | Cooked, |
| 29 | /// A raw string, like `r##"foo"##` |
| 30 | /// |
| 31 | /// The uint is the number of `#` symbols used |
| 32 | Raw(usize), |
| 33 | } |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 34 | } |
| 35 | |
Pascal Hertleif | 36342c5 | 2016-10-19 10:31:42 +0200 | [diff] [blame] | 36 | impl From<String> for Lit { |
| 37 | fn from(input: String) -> Lit { |
| 38 | Lit::Str(input, StrStyle::Cooked) |
| 39 | } |
| 40 | } |
| 41 | |
| 42 | impl<'a> From<&'a str> for Lit { |
| 43 | fn from(input: &str) -> Lit { |
| 44 | Lit::Str(input.into(), StrStyle::Cooked) |
| 45 | } |
| 46 | } |
| 47 | |
| 48 | impl From<Vec<u8>> for Lit { |
| 49 | fn from(input: Vec<u8>) -> Lit { |
David Tolnay | 4a65840 | 2016-10-24 00:21:41 -0700 | [diff] [blame] | 50 | Lit::ByteStr(input, StrStyle::Cooked) |
Pascal Hertleif | 36342c5 | 2016-10-19 10:31:42 +0200 | [diff] [blame] | 51 | } |
| 52 | } |
| 53 | |
| 54 | impl<'a> From<&'a [u8]> for Lit { |
| 55 | fn from(input: &[u8]) -> Lit { |
David Tolnay | 4a65840 | 2016-10-24 00:21:41 -0700 | [diff] [blame] | 56 | Lit::ByteStr(input.into(), StrStyle::Cooked) |
Pascal Hertleif | 36342c5 | 2016-10-19 10:31:42 +0200 | [diff] [blame] | 57 | } |
| 58 | } |
| 59 | |
| 60 | impl From<char> for Lit { |
| 61 | fn from(input: char) -> Lit { |
| 62 | Lit::Char(input) |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | impl From<bool> for Lit { |
| 67 | fn from(input: bool) -> Lit { |
| 68 | Lit::Bool(input) |
| 69 | } |
| 70 | } |
| 71 | |
Alex Crichton | 62a0a59 | 2017-05-22 13:58:53 -0700 | [diff] [blame] | 72 | ast_enum! { |
| 73 | #[derive(Copy)] |
Alex Crichton | 2e0229c | 2017-05-23 09:34:50 -0700 | [diff] [blame^] | 74 | #[cfg_attr(not(feature = "clone-impls"), derive(Clone))] |
Alex Crichton | 62a0a59 | 2017-05-22 13:58:53 -0700 | [diff] [blame] | 75 | pub enum IntTy { |
| 76 | Isize, |
| 77 | I8, |
| 78 | I16, |
| 79 | I32, |
| 80 | I64, |
| 81 | Usize, |
| 82 | U8, |
| 83 | U16, |
| 84 | U32, |
| 85 | U64, |
| 86 | Unsuffixed, |
| 87 | } |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 88 | } |
| 89 | |
Alex Crichton | 62a0a59 | 2017-05-22 13:58:53 -0700 | [diff] [blame] | 90 | ast_enum! { |
| 91 | #[derive(Copy)] |
Alex Crichton | 2e0229c | 2017-05-23 09:34:50 -0700 | [diff] [blame^] | 92 | #[cfg_attr(not(feature = "clone-impls"), derive(Clone))] |
Alex Crichton | 62a0a59 | 2017-05-22 13:58:53 -0700 | [diff] [blame] | 93 | pub enum FloatTy { |
| 94 | F32, |
| 95 | F64, |
| 96 | Unsuffixed, |
| 97 | } |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 98 | } |
| 99 | |
Pascal Hertleif | 36342c5 | 2016-10-19 10:31:42 +0200 | [diff] [blame] | 100 | macro_rules! impl_from_for_lit { |
| 101 | (Int, [$($rust_type:ty => $syn_type:expr),+]) => { |
| 102 | $( |
| 103 | impl From<$rust_type> for Lit { |
| 104 | fn from(input: $rust_type) -> Lit { |
| 105 | Lit::Int(input as u64, $syn_type) |
| 106 | } |
| 107 | } |
| 108 | )+ |
| 109 | }; |
| 110 | (Float, [$($rust_type:ty => $syn_type:expr),+]) => { |
| 111 | $( |
| 112 | impl From<$rust_type> for Lit { |
| 113 | fn from(input: $rust_type) -> Lit { |
| 114 | Lit::Float(format!("{}", input), $syn_type) |
| 115 | } |
| 116 | } |
| 117 | )+ |
| 118 | }; |
| 119 | } |
| 120 | |
| 121 | impl_from_for_lit! {Int, [ |
| 122 | isize => IntTy::Isize, |
| 123 | i8 => IntTy::I8, |
| 124 | i16 => IntTy::I16, |
| 125 | i32 => IntTy::I32, |
| 126 | i64 => IntTy::I64, |
| 127 | usize => IntTy::Usize, |
| 128 | u8 => IntTy::U8, |
| 129 | u16 => IntTy::U16, |
| 130 | u32 => IntTy::U32, |
| 131 | u64 => IntTy::U64 |
| 132 | ]} |
| 133 | |
| 134 | impl_from_for_lit! {Float, [ |
| 135 | f32 => FloatTy::F32, |
| 136 | f64 => FloatTy::F64 |
| 137 | ]} |
| 138 | |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 139 | #[cfg(feature = "parsing")] |
Alex Crichton | 2e0229c | 2017-05-23 09:34:50 -0700 | [diff] [blame^] | 140 | ast_struct! { |
| 141 | pub struct StrLit { |
| 142 | pub value: String, |
| 143 | pub style: StrStyle, |
| 144 | } |
David Tolnay | 5fe14fc | 2017-01-27 16:22:08 -0800 | [diff] [blame] | 145 | } |
| 146 | |
| 147 | #[cfg(feature = "parsing")] |
Alex Crichton | 2e0229c | 2017-05-23 09:34:50 -0700 | [diff] [blame^] | 148 | ast_struct! { |
| 149 | pub struct ByteStrLit { |
| 150 | pub value: Vec<u8>, |
| 151 | pub style: StrStyle, |
| 152 | } |
David Tolnay | 5fe14fc | 2017-01-27 16:22:08 -0800 | [diff] [blame] | 153 | } |
| 154 | |
| 155 | #[cfg(feature = "parsing")] |
Alex Crichton | 2e0229c | 2017-05-23 09:34:50 -0700 | [diff] [blame^] | 156 | ast_struct! { |
| 157 | pub struct IntLit { |
| 158 | pub value: u64, |
| 159 | pub suffix: IntTy, |
| 160 | } |
David Tolnay | 5fe14fc | 2017-01-27 16:22:08 -0800 | [diff] [blame] | 161 | } |
| 162 | |
| 163 | #[cfg(feature = "parsing")] |
Alex Crichton | 2e0229c | 2017-05-23 09:34:50 -0700 | [diff] [blame^] | 164 | ast_struct! { |
| 165 | pub struct FloatLit { |
| 166 | pub value: String, |
| 167 | pub suffix: FloatTy, |
| 168 | } |
David Tolnay | 5fe14fc | 2017-01-27 16:22:08 -0800 | [diff] [blame] | 169 | } |
| 170 | |
| 171 | #[cfg(feature = "parsing")] |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 172 | pub mod parsing { |
| 173 | use super::*; |
David Tolnay | fe373a3 | 2016-10-26 23:51:19 -0700 | [diff] [blame] | 174 | use escape::{cooked_byte, cooked_byte_string, cooked_char, cooked_string, raw_string}; |
David Tolnay | 5fe14fc | 2017-01-27 16:22:08 -0800 | [diff] [blame] | 175 | use synom::space::skip_whitespace; |
| 176 | use synom::IResult; |
David Tolnay | 4f5f60f | 2016-10-24 00:52:58 -0700 | [diff] [blame] | 177 | use unicode_xid::UnicodeXID; |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 178 | |
| 179 | named!(pub lit -> Lit, alt!( |
David Tolnay | 5fe14fc | 2017-01-27 16:22:08 -0800 | [diff] [blame] | 180 | string => { |StrLit { value, style }| Lit::Str(value, style) } |
David Tolnay | 56d6213 | 2016-10-01 16:14:54 -0700 | [diff] [blame] | 181 | | |
David Tolnay | 5fe14fc | 2017-01-27 16:22:08 -0800 | [diff] [blame] | 182 | byte_string => { |ByteStrLit { value, style }| Lit::ByteStr(value, style) } |
David Tolnay | 615cf6a | 2016-10-08 23:07:02 -0700 | [diff] [blame] | 183 | | |
Michael Layzell | 5e107ff | 2017-01-24 19:58:39 -0500 | [diff] [blame] | 184 | byte => { |b| Lit::Byte(b) } |
David Tolnay | 615cf6a | 2016-10-08 23:07:02 -0700 | [diff] [blame] | 185 | | |
Michael Layzell | 5e107ff | 2017-01-24 19:58:39 -0500 | [diff] [blame] | 186 | character => { |ch| Lit::Char(ch) } |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 187 | | |
David Tolnay | 5fe14fc | 2017-01-27 16:22:08 -0800 | [diff] [blame] | 188 | float => { |FloatLit { value, suffix }| Lit::Float(value, suffix) } // must be before int |
David Tolnay | 4f5f60f | 2016-10-24 00:52:58 -0700 | [diff] [blame] | 189 | | |
David Tolnay | 5fe14fc | 2017-01-27 16:22:08 -0800 | [diff] [blame] | 190 | int => { |IntLit { value, suffix }| Lit::Int(value, suffix) } |
David Tolnay | 759d2ff | 2016-10-01 16:18:15 -0700 | [diff] [blame] | 191 | | |
Michael Layzell | 5e107ff | 2017-01-24 19:58:39 -0500 | [diff] [blame] | 192 | boolean => { |value| Lit::Bool(value) } |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 193 | )); |
| 194 | |
David Tolnay | 5fe14fc | 2017-01-27 16:22:08 -0800 | [diff] [blame] | 195 | named!(pub string -> StrLit, alt!( |
| 196 | quoted_string => { |s| StrLit { value: s, style: StrStyle::Cooked } } |
David Tolnay | 210884d | 2016-10-01 08:18:42 -0700 | [diff] [blame] | 197 | | |
| 198 | preceded!( |
| 199 | punct!("r"), |
| 200 | raw_string |
David Tolnay | 5fe14fc | 2017-01-27 16:22:08 -0800 | [diff] [blame] | 201 | ) => { |(s, n)| StrLit { value: s, style: StrStyle::Raw(n) }} |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 202 | )); |
| 203 | |
David Tolnay | 4260229 | 2016-10-01 22:25:45 -0700 | [diff] [blame] | 204 | named!(pub quoted_string -> String, delimited!( |
| 205 | punct!("\""), |
| 206 | cooked_string, |
| 207 | tag!("\"") |
| 208 | )); |
| 209 | |
David Tolnay | 5fe14fc | 2017-01-27 16:22:08 -0800 | [diff] [blame] | 210 | named!(pub byte_string -> ByteStrLit, alt!( |
David Tolnay | 56d6213 | 2016-10-01 16:14:54 -0700 | [diff] [blame] | 211 | delimited!( |
| 212 | punct!("b\""), |
David Tolnay | a73e0f0 | 2016-10-26 23:25:49 -0700 | [diff] [blame] | 213 | cooked_byte_string, |
David Tolnay | 56d6213 | 2016-10-01 16:14:54 -0700 | [diff] [blame] | 214 | tag!("\"") |
David Tolnay | 5fe14fc | 2017-01-27 16:22:08 -0800 | [diff] [blame] | 215 | ) => { |vec| ByteStrLit { value: vec, style: StrStyle::Cooked } } |
David Tolnay | 56d6213 | 2016-10-01 16:14:54 -0700 | [diff] [blame] | 216 | | |
| 217 | preceded!( |
| 218 | punct!("br"), |
| 219 | raw_string |
David Tolnay | 5fe14fc | 2017-01-27 16:22:08 -0800 | [diff] [blame] | 220 | ) => { |(s, n): (String, _)| ByteStrLit { value: s.into_bytes(), style: StrStyle::Raw(n) } } |
David Tolnay | 56d6213 | 2016-10-01 16:14:54 -0700 | [diff] [blame] | 221 | )); |
| 222 | |
Michael Layzell | 5e107ff | 2017-01-24 19:58:39 -0500 | [diff] [blame] | 223 | named!(pub byte -> u8, do_parse!( |
David Tolnay | 615cf6a | 2016-10-08 23:07:02 -0700 | [diff] [blame] | 224 | punct!("b") >> |
| 225 | tag!("'") >> |
David Tolnay | fe373a3 | 2016-10-26 23:51:19 -0700 | [diff] [blame] | 226 | b: cooked_byte >> |
David Tolnay | 615cf6a | 2016-10-08 23:07:02 -0700 | [diff] [blame] | 227 | tag!("'") >> |
Michael Layzell | 5e107ff | 2017-01-24 19:58:39 -0500 | [diff] [blame] | 228 | (b) |
David Tolnay | 615cf6a | 2016-10-08 23:07:02 -0700 | [diff] [blame] | 229 | )); |
| 230 | |
Michael Layzell | 5e107ff | 2017-01-24 19:58:39 -0500 | [diff] [blame] | 231 | named!(pub character -> char, do_parse!( |
David Tolnay | 615cf6a | 2016-10-08 23:07:02 -0700 | [diff] [blame] | 232 | punct!("'") >> |
| 233 | ch: cooked_char >> |
| 234 | tag!("'") >> |
Michael Layzell | 5e107ff | 2017-01-24 19:58:39 -0500 | [diff] [blame] | 235 | (ch) |
David Tolnay | 615cf6a | 2016-10-08 23:07:02 -0700 | [diff] [blame] | 236 | )); |
| 237 | |
David Tolnay | 5fe14fc | 2017-01-27 16:22:08 -0800 | [diff] [blame] | 238 | named!(pub float -> FloatLit, do_parse!( |
| 239 | value: float_string >> |
| 240 | suffix: alt!( |
David Tolnay | 4f5f60f | 2016-10-24 00:52:58 -0700 | [diff] [blame] | 241 | tag!("f32") => { |_| FloatTy::F32 } |
| 242 | | |
| 243 | tag!("f64") => { |_| FloatTy::F64 } |
| 244 | | |
| 245 | epsilon!() => { |_| FloatTy::Unsuffixed } |
David Tolnay | 5fe14fc | 2017-01-27 16:22:08 -0800 | [diff] [blame] | 246 | ) >> |
| 247 | (FloatLit { value: value, suffix: suffix }) |
David Tolnay | 4f5f60f | 2016-10-24 00:52:58 -0700 | [diff] [blame] | 248 | )); |
| 249 | |
David Tolnay | 5fe14fc | 2017-01-27 16:22:08 -0800 | [diff] [blame] | 250 | named!(pub int -> IntLit, do_parse!( |
| 251 | value: digits >> |
| 252 | suffix: alt!( |
David Tolnay | de20622 | 2016-09-30 11:47:01 -0700 | [diff] [blame] | 253 | tag!("isize") => { |_| IntTy::Isize } |
| 254 | | |
| 255 | tag!("i8") => { |_| IntTy::I8 } |
| 256 | | |
| 257 | tag!("i16") => { |_| IntTy::I16 } |
| 258 | | |
| 259 | tag!("i32") => { |_| IntTy::I32 } |
| 260 | | |
| 261 | tag!("i64") => { |_| IntTy::I64 } |
| 262 | | |
| 263 | tag!("usize") => { |_| IntTy::Usize } |
| 264 | | |
| 265 | tag!("u8") => { |_| IntTy::U8 } |
| 266 | | |
| 267 | tag!("u16") => { |_| IntTy::U16 } |
| 268 | | |
| 269 | tag!("u32") => { |_| IntTy::U32 } |
| 270 | | |
| 271 | tag!("u64") => { |_| IntTy::U64 } |
| 272 | | |
| 273 | epsilon!() => { |_| IntTy::Unsuffixed } |
David Tolnay | 5fe14fc | 2017-01-27 16:22:08 -0800 | [diff] [blame] | 274 | ) >> |
| 275 | (IntLit { value: value, suffix: suffix }) |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 276 | )); |
| 277 | |
Michael Layzell | 5e107ff | 2017-01-24 19:58:39 -0500 | [diff] [blame] | 278 | named!(pub boolean -> bool, alt!( |
| 279 | keyword!("true") => { |_| true } |
David Tolnay | 3ce49d0 | 2016-10-23 22:29:19 -0700 | [diff] [blame] | 280 | | |
Michael Layzell | 5e107ff | 2017-01-24 19:58:39 -0500 | [diff] [blame] | 281 | keyword!("false") => { |_| false } |
David Tolnay | 3ce49d0 | 2016-10-23 22:29:19 -0700 | [diff] [blame] | 282 | )); |
| 283 | |
David Tolnay | def6637 | 2016-10-24 21:51:32 -0700 | [diff] [blame] | 284 | fn float_string(mut input: &str) -> IResult<&str, String> { |
| 285 | input = skip_whitespace(input); |
| 286 | |
David Tolnay | 4f5f60f | 2016-10-24 00:52:58 -0700 | [diff] [blame] | 287 | let mut chars = input.chars().peekable(); |
| 288 | match chars.next() { |
| 289 | Some(ch) if ch >= '0' && ch <= '9' => {} |
| 290 | _ => return IResult::Error, |
| 291 | } |
| 292 | |
| 293 | let mut len = 1; |
| 294 | let mut has_dot = false; |
| 295 | let mut has_exp = false; |
| 296 | while let Some(&ch) = chars.peek() { |
| 297 | match ch { |
| 298 | '0'...'9' | '_' => { |
| 299 | chars.next(); |
| 300 | len += 1; |
| 301 | } |
| 302 | '.' => { |
| 303 | if has_dot { |
| 304 | break; |
| 305 | } |
| 306 | chars.next(); |
| 307 | if chars.peek() |
David Tolnay | 05120ef | 2017-03-12 18:29:26 -0700 | [diff] [blame] | 308 | .map(|&ch| ch == '.' || UnicodeXID::is_xid_start(ch)) |
| 309 | .unwrap_or(false) { |
David Tolnay | 4f5f60f | 2016-10-24 00:52:58 -0700 | [diff] [blame] | 310 | return IResult::Error; |
| 311 | } |
| 312 | len += 1; |
| 313 | has_dot = true; |
| 314 | } |
| 315 | 'e' | 'E' => { |
| 316 | chars.next(); |
| 317 | len += 1; |
| 318 | has_exp = true; |
| 319 | break; |
| 320 | } |
| 321 | _ => break, |
| 322 | } |
| 323 | } |
| 324 | |
| 325 | let rest = &input[len..]; |
| 326 | if !(has_dot || has_exp || rest.starts_with("f32") || rest.starts_with("f64")) { |
| 327 | return IResult::Error; |
| 328 | } |
| 329 | |
| 330 | if has_exp { |
| 331 | let mut has_exp_value = false; |
| 332 | while let Some(&ch) = chars.peek() { |
| 333 | match ch { |
| 334 | '+' | '-' => { |
| 335 | if has_exp_value { |
| 336 | break; |
| 337 | } |
| 338 | chars.next(); |
| 339 | len += 1; |
| 340 | } |
| 341 | '0'...'9' => { |
| 342 | chars.next(); |
| 343 | len += 1; |
| 344 | has_exp_value = true; |
| 345 | } |
| 346 | '_' => { |
| 347 | chars.next(); |
| 348 | len += 1; |
| 349 | } |
| 350 | _ => break, |
| 351 | } |
| 352 | } |
| 353 | if !has_exp_value { |
| 354 | return IResult::Error; |
| 355 | } |
| 356 | } |
| 357 | |
David Tolnay | c7b636a | 2016-10-24 13:01:08 -0700 | [diff] [blame] | 358 | IResult::Done(&input[len..], input[..len].replace("_", "")) |
David Tolnay | 4f5f60f | 2016-10-24 00:52:58 -0700 | [diff] [blame] | 359 | } |
| 360 | |
David Tolnay | 8a19e6d | 2016-10-24 01:23:40 -0700 | [diff] [blame] | 361 | pub fn digits(mut input: &str) -> IResult<&str, u64> { |
David Tolnay | def6637 | 2016-10-24 21:51:32 -0700 | [diff] [blame] | 362 | input = skip_whitespace(input); |
| 363 | |
David Tolnay | 8a19e6d | 2016-10-24 01:23:40 -0700 | [diff] [blame] | 364 | let base = if input.starts_with("0x") { |
| 365 | input = &input[2..]; |
| 366 | 16 |
| 367 | } else if input.starts_with("0o") { |
| 368 | input = &input[2..]; |
| 369 | 8 |
| 370 | } else if input.starts_with("0b") { |
| 371 | input = &input[2..]; |
| 372 | 2 |
| 373 | } else { |
| 374 | 10 |
| 375 | }; |
| 376 | |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 377 | let mut value = 0u64; |
| 378 | let mut len = 0; |
David Tolnay | 24b5ff7 | 2016-10-24 01:05:05 -0700 | [diff] [blame] | 379 | let mut empty = true; |
| 380 | for b in input.bytes() { |
David Tolnay | 8a19e6d | 2016-10-24 01:23:40 -0700 | [diff] [blame] | 381 | let digit = match b { |
| 382 | b'0'...b'9' => (b - b'0') as u64, |
| 383 | b'a'...b'f' => 10 + (b - b'a') as u64, |
| 384 | b'A'...b'F' => 10 + (b - b'A') as u64, |
David Tolnay | 24b5ff7 | 2016-10-24 01:05:05 -0700 | [diff] [blame] | 385 | b'_' => { |
David Tolnay | c814a76 | 2016-10-27 23:11:28 -0700 | [diff] [blame] | 386 | if empty && base == 10 { |
David Tolnay | 24b5ff7 | 2016-10-24 01:05:05 -0700 | [diff] [blame] | 387 | return IResult::Error; |
| 388 | } |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 389 | len += 1; |
David Tolnay | 8a19e6d | 2016-10-24 01:23:40 -0700 | [diff] [blame] | 390 | continue; |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 391 | } |
David Tolnay | fa0edf2 | 2016-09-23 22:58:24 -0700 | [diff] [blame] | 392 | _ => break, |
David Tolnay | 8a19e6d | 2016-10-24 01:23:40 -0700 | [diff] [blame] | 393 | }; |
| 394 | if digit >= base { |
| 395 | return IResult::Error; |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 396 | } |
David Tolnay | 8a19e6d | 2016-10-24 01:23:40 -0700 | [diff] [blame] | 397 | value = match value.checked_mul(base) { |
| 398 | Some(value) => value, |
| 399 | None => return IResult::Error, |
| 400 | }; |
| 401 | value = match value.checked_add(digit) { |
| 402 | Some(value) => value, |
| 403 | None => return IResult::Error, |
| 404 | }; |
| 405 | len += 1; |
| 406 | empty = false; |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 407 | } |
David Tolnay | 24b5ff7 | 2016-10-24 01:05:05 -0700 | [diff] [blame] | 408 | if empty { |
David Tolnay | fa0edf2 | 2016-09-23 22:58:24 -0700 | [diff] [blame] | 409 | IResult::Error |
David Tolnay | 24b5ff7 | 2016-10-24 01:05:05 -0700 | [diff] [blame] | 410 | } else { |
| 411 | IResult::Done(&input[len..], value) |
David Tolnay | fa0edf2 | 2016-09-23 22:58:24 -0700 | [diff] [blame] | 412 | } |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 413 | } |
| 414 | } |
| 415 | |
| 416 | #[cfg(feature = "printing")] |
| 417 | mod printing { |
| 418 | use super::*; |
| 419 | use quote::{Tokens, ToTokens}; |
David Tolnay | 56d6213 | 2016-10-01 16:14:54 -0700 | [diff] [blame] | 420 | use std::{ascii, iter}; |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 421 | use std::fmt::{self, Display}; |
David Tolnay | 4a65840 | 2016-10-24 00:21:41 -0700 | [diff] [blame] | 422 | use std::str; |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 423 | |
| 424 | impl ToTokens for Lit { |
| 425 | fn to_tokens(&self, tokens: &mut Tokens) { |
| 426 | match *self { |
| 427 | Lit::Str(ref s, StrStyle::Cooked) => s.to_tokens(tokens), |
David Tolnay | 627e3d5 | 2016-10-01 08:27:31 -0700 | [diff] [blame] | 428 | Lit::Str(ref s, StrStyle::Raw(n)) => { |
David Tolnay | 56d6213 | 2016-10-01 16:14:54 -0700 | [diff] [blame] | 429 | tokens.append(&format!("r{delim}\"{string}\"{delim}", |
David Tolnay | 05120ef | 2017-03-12 18:29:26 -0700 | [diff] [blame] | 430 | delim = iter::repeat("#").take(n).collect::<String>(), |
| 431 | string = s)); |
David Tolnay | 56d6213 | 2016-10-01 16:14:54 -0700 | [diff] [blame] | 432 | } |
David Tolnay | 4a65840 | 2016-10-24 00:21:41 -0700 | [diff] [blame] | 433 | Lit::ByteStr(ref v, StrStyle::Cooked) => { |
David Tolnay | 56d6213 | 2016-10-01 16:14:54 -0700 | [diff] [blame] | 434 | let mut escaped = "b\"".to_string(); |
| 435 | for &ch in v.iter() { |
David Tolnay | 289f4c7 | 2016-10-25 00:00:09 -0700 | [diff] [blame] | 436 | match ch { |
| 437 | 0 => escaped.push_str(r"\0"), |
| 438 | b'\'' => escaped.push('\''), |
| 439 | _ => escaped.extend(ascii::escape_default(ch).map(|c| c as char)), |
| 440 | } |
David Tolnay | 627e3d5 | 2016-10-01 08:27:31 -0700 | [diff] [blame] | 441 | } |
David Tolnay | 56d6213 | 2016-10-01 16:14:54 -0700 | [diff] [blame] | 442 | escaped.push('"'); |
| 443 | tokens.append(&escaped); |
David Tolnay | 627e3d5 | 2016-10-01 08:27:31 -0700 | [diff] [blame] | 444 | } |
David Tolnay | 4a65840 | 2016-10-24 00:21:41 -0700 | [diff] [blame] | 445 | Lit::ByteStr(ref vec, StrStyle::Raw(n)) => { |
| 446 | tokens.append(&format!("br{delim}\"{string}\"{delim}", |
David Tolnay | 05120ef | 2017-03-12 18:29:26 -0700 | [diff] [blame] | 447 | delim = iter::repeat("#").take(n).collect::<String>(), |
| 448 | string = str::from_utf8(vec).unwrap())); |
David Tolnay | 4a65840 | 2016-10-24 00:21:41 -0700 | [diff] [blame] | 449 | } |
David Tolnay | 289f4c7 | 2016-10-25 00:00:09 -0700 | [diff] [blame] | 450 | Lit::Byte(b) => { |
| 451 | match b { |
| 452 | 0 => tokens.append(r"b'\0'"), |
| 453 | b'\"' => tokens.append("b'\"'"), |
| 454 | _ => { |
| 455 | let mut escaped = "b'".to_string(); |
| 456 | escaped.extend(ascii::escape_default(b).map(|c| c as char)); |
| 457 | escaped.push('\''); |
| 458 | tokens.append(&escaped); |
| 459 | } |
| 460 | } |
| 461 | } |
David Tolnay | f17fd2f | 2016-10-07 23:38:08 -0700 | [diff] [blame] | 462 | Lit::Char(ch) => ch.to_tokens(tokens), |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 463 | Lit::Int(value, ty) => tokens.append(&format!("{}{}", value, ty)), |
David Tolnay | f17fd2f | 2016-10-07 23:38:08 -0700 | [diff] [blame] | 464 | Lit::Float(ref value, ty) => tokens.append(&format!("{}{}", value, ty)), |
David Tolnay | 759d2ff | 2016-10-01 16:18:15 -0700 | [diff] [blame] | 465 | Lit::Bool(true) => tokens.append("true"), |
| 466 | Lit::Bool(false) => tokens.append("false"), |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 467 | } |
| 468 | } |
| 469 | } |
| 470 | |
| 471 | impl Display for IntTy { |
| 472 | fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { |
| 473 | match *self { |
| 474 | IntTy::Isize => formatter.write_str("isize"), |
| 475 | IntTy::I8 => formatter.write_str("i8"), |
| 476 | IntTy::I16 => formatter.write_str("i16"), |
| 477 | IntTy::I32 => formatter.write_str("i32"), |
| 478 | IntTy::I64 => formatter.write_str("i64"), |
| 479 | IntTy::Usize => formatter.write_str("usize"), |
| 480 | IntTy::U8 => formatter.write_str("u8"), |
| 481 | IntTy::U16 => formatter.write_str("u16"), |
| 482 | IntTy::U32 => formatter.write_str("u32"), |
| 483 | IntTy::U64 => formatter.write_str("u64"), |
| 484 | IntTy::Unsuffixed => Ok(()), |
| 485 | } |
| 486 | } |
| 487 | } |
David Tolnay | f17fd2f | 2016-10-07 23:38:08 -0700 | [diff] [blame] | 488 | |
| 489 | impl Display for FloatTy { |
| 490 | fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { |
| 491 | match *self { |
| 492 | FloatTy::F32 => formatter.write_str("f32"), |
| 493 | FloatTy::F64 => formatter.write_str("f64"), |
| 494 | FloatTy::Unsuffixed => Ok(()), |
| 495 | } |
| 496 | } |
| 497 | } |
David Tolnay | f4bbbd9 | 2016-09-23 14:41:55 -0700 | [diff] [blame] | 498 | } |