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