blob: 8e277ad62a4610aa1f401e99c750a8c071d2ffe2 [file] [log] [blame]
David Tolnayf4bbbd92016-09-23 14:41:55 -07001/// Literal kind.
2///
3/// E.g. `"foo"`, `42`, `12.34` or `bool`
4#[derive(Debug, Clone, Eq, PartialEq)]
5pub enum Lit {
6 /// A string literal (`"foo"`)
7 Str(String, StrStyle),
8 /// A byte string (`b"foo"`)
9 ByteStr(Vec<u8>),
10 /// A byte char (`b'f'`)
11 Byte(u8),
12 /// A character literal (`'a'`)
13 Char(char),
14 /// An integer literal (`1`)
15 Int(u64, IntTy),
16 /// A float literal (`1f64` or `1E10f64` or `1.0E10`)
17 Float(String, FloatTy),
18 /// A boolean literal
19 Bool(bool),
20}
21
22#[derive(Debug, Copy, Clone, Eq, PartialEq)]
23pub enum StrStyle {
24 /// A regular string, like `"foo"`
25 Cooked,
26 /// A raw string, like `r##"foo"##`
27 ///
28 /// The uint is the number of `#` symbols used
29 Raw(usize)
30}
31
32#[derive(Debug, Copy, Clone, Eq, PartialEq)]
33pub enum IntTy {
34 Isize,
35 I8,
36 I16,
37 I32,
38 I64,
39 Usize,
40 U8,
41 U16,
42 U32,
43 U64,
44 Unsuffixed
45}
46
47#[derive(Debug, Copy, Clone, Eq, PartialEq)]
48pub enum FloatTy {
49 F32,
50 F64,
51 Unsuffixed,
52}
53
54#[cfg(feature = "parsing")]
55pub mod parsing {
56 use super::*;
57 use escape::escaped_string;
58 use nom::{IResult, multispace};
59
60 named!(pub lit -> Lit, alt!(
David Tolnayf4bbbd92016-09-23 14:41:55 -070061 quoted => { |q| Lit::Str(q, StrStyle::Cooked) }
David Tolnay7de67d22016-09-24 07:23:32 -070062 // TODO: ByteStr
63 // TODO: Byte
64 // TODO: Char
David Tolnayf4bbbd92016-09-23 14:41:55 -070065 |
66 int => { |(value, ty)| Lit::Int(value, ty) }
David Tolnay7de67d22016-09-24 07:23:32 -070067 // TODO: Float
68 // TODO: Bool
David Tolnayf4bbbd92016-09-23 14:41:55 -070069 ));
70
71 named!(quoted -> String, delimited!(
72 punct!("\""),
73 escaped_string,
74 tag!("\"")
75 ));
76
77 named!(pub int -> (u64, IntTy), preceded!(
78 option!(multispace),
79 tuple!(
80 digits,
81 alt!(
82 tag!("isize") => { |_| IntTy::Isize }
83 |
84 tag!("i8") => { |_| IntTy::I8 }
85 |
86 tag!("i16") => { |_| IntTy::I16 }
87 |
88 tag!("i32") => { |_| IntTy::I32 }
89 |
90 tag!("i64") => { |_| IntTy::I64 }
91 |
92 tag!("usize") => { |_| IntTy::Usize }
93 |
94 tag!("u8") => { |_| IntTy::U8 }
95 |
96 tag!("u16") => { |_| IntTy::U16 }
97 |
98 tag!("u32") => { |_| IntTy::U32 }
99 |
100 tag!("u64") => { |_| IntTy::U64 }
101 |
102 epsilon!() => { |_| IntTy::Unsuffixed }
103 )
104 )
105 ));
106
107 fn digits(input: &str) -> IResult<&str, u64> {
108 let mut value = 0u64;
109 let mut len = 0;
110 let mut bytes = input.bytes().peekable();
111 while let Some(&b) = bytes.peek() {
112 match b {
113 b'0' ... b'9' => {
114 value = match value.checked_mul(10) {
115 Some(value) => value,
116 None => return IResult::Error,
117 };
118 value = match value.checked_add((b - b'0') as u64) {
119 Some(value) => value,
120 None => return IResult::Error,
121 };
122 bytes.next();
123 len += 1;
124 }
David Tolnayfa0edf22016-09-23 22:58:24 -0700125 _ => break,
David Tolnayf4bbbd92016-09-23 14:41:55 -0700126 }
127 }
David Tolnayfa0edf22016-09-23 22:58:24 -0700128 if len > 0 {
129 IResult::Done(&input[len..], value)
130 } else {
131 IResult::Error
132 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700133 }
134}
135
136#[cfg(feature = "printing")]
137mod printing {
138 use super::*;
139 use quote::{Tokens, ToTokens};
140 use std::fmt::{self, Display};
141
142 impl ToTokens for Lit {
143 fn to_tokens(&self, tokens: &mut Tokens) {
144 match *self {
145 Lit::Str(ref s, StrStyle::Cooked) => s.to_tokens(tokens),
146 Lit::Int(value, ty) => tokens.append(&format!("{}{}", value, ty)),
147 _ => unimplemented!(),
148 }
149 }
150 }
151
152 impl Display for IntTy {
153 fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
154 match *self {
155 IntTy::Isize => formatter.write_str("isize"),
156 IntTy::I8 => formatter.write_str("i8"),
157 IntTy::I16 => formatter.write_str("i16"),
158 IntTy::I32 => formatter.write_str("i32"),
159 IntTy::I64 => formatter.write_str("i64"),
160 IntTy::Usize => formatter.write_str("usize"),
161 IntTy::U8 => formatter.write_str("u8"),
162 IntTy::U16 => formatter.write_str("u16"),
163 IntTy::U32 => formatter.write_str("u32"),
164 IntTy::U64 => formatter.write_str("u64"),
165 IntTy::Unsuffixed => Ok(()),
166 }
167 }
168 }
169}