1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
use crate::{
BoolLit,
Buffer,
ByteLit,
ByteStringLit,
CharLit,
Error,
ErrorKind,
FloatLit,
IntegerLit,
Literal,
StringLit,
};
impl<B: Buffer> Literal<B> {
pub fn parse(input: B) -> Result<Self, Error> {
let first = first_byte_or_empty(&input)?;
let second = input.as_bytes().get(1).copied();
match first {
b'f' if &*input == "false" => Ok(Self::Bool(BoolLit::False)),
b't' if &*input == "true" => Ok(Self::Bool(BoolLit::True)),
digit @ b'0'..=b'9' => {
let end = 1 + end_dec_digits(&input[1..]);
match input.as_bytes().get(end) {
None | Some(b'b') | Some(b'o') | Some(b'x') | Some(b'u') | Some(b'i')
=> IntegerLit::parse_impl(input, digit).map(Literal::Integer),
Some(b'.') | Some(b'e') | Some(b'E') | Some(b'f')
=> FloatLit::parse_impl(input).map(Literal::Float),
_ => Err(Error::single(end, ErrorKind::UnexpectedChar)),
}
},
b'\'' => CharLit::parse_impl(input).map(Literal::Char),
b'"' | b'r' => StringLit::parse_impl(input).map(Literal::String),
b'b' if second == Some(b'\'') => ByteLit::parse_impl(input).map(Literal::Byte),
b'b' if second == Some(b'r') || second == Some(b'"')
=> ByteStringLit::parse_impl(input).map(Literal::ByteString),
_ => Err(Error::spanless(ErrorKind::InvalidLiteral)),
}
}
}
pub(crate) fn first_byte_or_empty(s: &str) -> Result<u8, Error> {
s.as_bytes().get(0).copied().ok_or(Error::spanless(ErrorKind::Empty))
}
pub(crate) fn end_dec_digits(input: &str) -> usize {
input.bytes()
.position(|b| !matches!(b, b'_' | b'0'..=b'9'))
.unwrap_or(input.len())
}
pub(crate) fn hex_digit_value(digit: u8) -> Option<u8> {
match digit {
b'0'..=b'9' => Some(digit - b'0'),
b'a'..=b'f' => Some(digit - b'a' + 10),
b'A'..=b'F' => Some(digit - b'A' + 10),
_ => None,
}
}