167c3a3e4Sopenharmony_ci// (C) Copyright 2016 Jethro G. Beekman
267c3a3e4Sopenharmony_ci//
367c3a3e4Sopenharmony_ci// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
467c3a3e4Sopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
567c3a3e4Sopenharmony_ci// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
667c3a3e4Sopenharmony_ci// option. This file may not be copied, modified, or distributed
767c3a3e4Sopenharmony_ci// except according to those terms.
867c3a3e4Sopenharmony_ci//! Parsing C literals from byte slices.
967c3a3e4Sopenharmony_ci//!
1067c3a3e4Sopenharmony_ci//! This will parse a representation of a C literal into a Rust type.
1167c3a3e4Sopenharmony_ci//!
1267c3a3e4Sopenharmony_ci//! # characters
1367c3a3e4Sopenharmony_ci//! Character literals are stored into the `CChar` type, which can hold values
1467c3a3e4Sopenharmony_ci//! that are not valid Unicode code points. ASCII characters are represented as
1567c3a3e4Sopenharmony_ci//! `char`, literal bytes with the high byte set are converted into the raw
1667c3a3e4Sopenharmony_ci//! representation. Escape sequences are supported. If hex and octal escapes
1767c3a3e4Sopenharmony_ci//! map to an ASCII character, that is used, otherwise, the raw encoding is
1867c3a3e4Sopenharmony_ci//! used, including for values over 255. Unicode escapes are checked for
1967c3a3e4Sopenharmony_ci//! validity and mapped to `char`. Character sequences are not supported. Width
2067c3a3e4Sopenharmony_ci//! prefixes are ignored.
2167c3a3e4Sopenharmony_ci//!
2267c3a3e4Sopenharmony_ci//! # strings
2367c3a3e4Sopenharmony_ci//! Strings are interpreted as byte vectors. Escape sequences are supported. If
2467c3a3e4Sopenharmony_ci//! hex and octal escapes map onto multi-byte characters, they are truncated to
2567c3a3e4Sopenharmony_ci//! one 8-bit character. Unicode escapes are converted into their UTF-8
2667c3a3e4Sopenharmony_ci//! encoding. Width prefixes are ignored.
2767c3a3e4Sopenharmony_ci//!
2867c3a3e4Sopenharmony_ci//! # integers
2967c3a3e4Sopenharmony_ci//! Integers are read into `i64`. Binary, octal, decimal and hexadecimal are
3067c3a3e4Sopenharmony_ci//! all supported. If the literal value is between `i64::MAX` and `u64::MAX`,
3167c3a3e4Sopenharmony_ci//! it is bit-cast to `i64`. Values over `u64::MAX` cannot be parsed. Width and
3267c3a3e4Sopenharmony_ci//! sign suffixes are ignored. Sign prefixes are not supported.
3367c3a3e4Sopenharmony_ci//!
3467c3a3e4Sopenharmony_ci//! # real numbers
3567c3a3e4Sopenharmony_ci//! Reals are read into `f64`. Width suffixes are ignored. Sign prefixes are
3667c3a3e4Sopenharmony_ci//! not supported in the significand. Hexadecimal floating points are not
3767c3a3e4Sopenharmony_ci//! supported.
3867c3a3e4Sopenharmony_ci
3967c3a3e4Sopenharmony_ciuse std::char;
4067c3a3e4Sopenharmony_ciuse std::str::{self, FromStr};
4167c3a3e4Sopenharmony_ci
4267c3a3e4Sopenharmony_ciuse nom::branch::alt;
4367c3a3e4Sopenharmony_ciuse nom::bytes::complete::is_not;
4467c3a3e4Sopenharmony_ciuse nom::bytes::complete::tag;
4567c3a3e4Sopenharmony_ciuse nom::character::complete::{char, one_of};
4667c3a3e4Sopenharmony_ciuse nom::combinator::{complete, map, map_opt, opt, recognize};
4767c3a3e4Sopenharmony_ciuse nom::multi::{fold_many0, many0, many1, many_m_n};
4867c3a3e4Sopenharmony_ciuse nom::sequence::{delimited, pair, preceded, terminated, tuple};
4967c3a3e4Sopenharmony_ciuse nom::*;
5067c3a3e4Sopenharmony_ci
5167c3a3e4Sopenharmony_ciuse crate::expr::EvalResult;
5267c3a3e4Sopenharmony_ciuse crate::ToCexprResult;
5367c3a3e4Sopenharmony_ci
5467c3a3e4Sopenharmony_ci#[derive(Debug, Copy, Clone, PartialEq, Eq)]
5567c3a3e4Sopenharmony_ci/// Representation of a C character
5667c3a3e4Sopenharmony_cipub enum CChar {
5767c3a3e4Sopenharmony_ci    /// A character that can be represented as a `char`
5867c3a3e4Sopenharmony_ci    Char(char),
5967c3a3e4Sopenharmony_ci    /// Any other character (8-bit characters, unicode surrogates, etc.)
6067c3a3e4Sopenharmony_ci    Raw(u64),
6167c3a3e4Sopenharmony_ci}
6267c3a3e4Sopenharmony_ci
6367c3a3e4Sopenharmony_ciimpl From<u8> for CChar {
6467c3a3e4Sopenharmony_ci    fn from(i: u8) -> CChar {
6567c3a3e4Sopenharmony_ci        match i {
6667c3a3e4Sopenharmony_ci            0..=0x7f => CChar::Char(i as u8 as char),
6767c3a3e4Sopenharmony_ci            _ => CChar::Raw(i as u64),
6867c3a3e4Sopenharmony_ci        }
6967c3a3e4Sopenharmony_ci    }
7067c3a3e4Sopenharmony_ci}
7167c3a3e4Sopenharmony_ci
7267c3a3e4Sopenharmony_ci// A non-allocating version of this would be nice...
7367c3a3e4Sopenharmony_ciimpl std::convert::Into<Vec<u8>> for CChar {
7467c3a3e4Sopenharmony_ci    fn into(self) -> Vec<u8> {
7567c3a3e4Sopenharmony_ci        match self {
7667c3a3e4Sopenharmony_ci            CChar::Char(c) => {
7767c3a3e4Sopenharmony_ci                let mut s = String::with_capacity(4);
7867c3a3e4Sopenharmony_ci                s.extend(&[c]);
7967c3a3e4Sopenharmony_ci                s.into_bytes()
8067c3a3e4Sopenharmony_ci            }
8167c3a3e4Sopenharmony_ci            CChar::Raw(i) => {
8267c3a3e4Sopenharmony_ci                let mut v = Vec::with_capacity(1);
8367c3a3e4Sopenharmony_ci                v.push(i as u8);
8467c3a3e4Sopenharmony_ci                v
8567c3a3e4Sopenharmony_ci            }
8667c3a3e4Sopenharmony_ci        }
8767c3a3e4Sopenharmony_ci    }
8867c3a3e4Sopenharmony_ci}
8967c3a3e4Sopenharmony_ci
9067c3a3e4Sopenharmony_ci/// ensures the child parser consumes the whole input
9167c3a3e4Sopenharmony_cipub fn full<I: Clone, O, F>(
9267c3a3e4Sopenharmony_ci    f: F,
9367c3a3e4Sopenharmony_ci) -> impl Fn(I) -> nom::IResult<I, O>
9467c3a3e4Sopenharmony_ciwhere
9567c3a3e4Sopenharmony_ci    I: nom::InputLength,
9667c3a3e4Sopenharmony_ci    F: Fn(I) -> nom::IResult<I, O>,
9767c3a3e4Sopenharmony_ci{
9867c3a3e4Sopenharmony_ci    move |input| {
9967c3a3e4Sopenharmony_ci        let res = f(input);
10067c3a3e4Sopenharmony_ci        match res {
10167c3a3e4Sopenharmony_ci            Ok((i, o)) => {
10267c3a3e4Sopenharmony_ci                if i.input_len() == 0 {
10367c3a3e4Sopenharmony_ci                    Ok((i, o))
10467c3a3e4Sopenharmony_ci                } else {
10567c3a3e4Sopenharmony_ci                    Err(nom::Err::Error(nom::error::Error::new(i, nom::error::ErrorKind::Complete)))
10667c3a3e4Sopenharmony_ci                }
10767c3a3e4Sopenharmony_ci            }
10867c3a3e4Sopenharmony_ci            r => r,
10967c3a3e4Sopenharmony_ci        }
11067c3a3e4Sopenharmony_ci    }
11167c3a3e4Sopenharmony_ci}
11267c3a3e4Sopenharmony_ci
11367c3a3e4Sopenharmony_ci// =================================
11467c3a3e4Sopenharmony_ci// ======== matching digits ========
11567c3a3e4Sopenharmony_ci// =================================
11667c3a3e4Sopenharmony_ci
11767c3a3e4Sopenharmony_cimacro_rules! byte {
11867c3a3e4Sopenharmony_ci	($($p: pat)|* ) => {{
11967c3a3e4Sopenharmony_ci        fn parser(i: &[u8]) -> crate::nom::IResult<&[u8], u8> {
12067c3a3e4Sopenharmony_ci            match i.split_first() {
12167c3a3e4Sopenharmony_ci                $(Some((&c @ $p,rest)))|* => Ok((rest,c)),
12267c3a3e4Sopenharmony_ci                Some(_) => Err(nom::Err::Error(nom::error::Error::new(i, nom::error::ErrorKind::OneOf))),
12367c3a3e4Sopenharmony_ci                None => Err(nom::Err::Incomplete(Needed::new(1))),
12467c3a3e4Sopenharmony_ci            }
12567c3a3e4Sopenharmony_ci        }
12667c3a3e4Sopenharmony_ci
12767c3a3e4Sopenharmony_ci        parser
12867c3a3e4Sopenharmony_ci	}}
12967c3a3e4Sopenharmony_ci}
13067c3a3e4Sopenharmony_ci
13167c3a3e4Sopenharmony_cifn binary(i: &[u8]) -> nom::IResult<&[u8], u8> {
13267c3a3e4Sopenharmony_ci    byte!(b'0'..=b'1')(i)
13367c3a3e4Sopenharmony_ci}
13467c3a3e4Sopenharmony_ci
13567c3a3e4Sopenharmony_cifn octal(i: &[u8]) -> nom::IResult<&[u8], u8> {
13667c3a3e4Sopenharmony_ci    byte!(b'0'..=b'7')(i)
13767c3a3e4Sopenharmony_ci}
13867c3a3e4Sopenharmony_ci
13967c3a3e4Sopenharmony_cifn decimal(i: &[u8]) -> nom::IResult<&[u8], u8> {
14067c3a3e4Sopenharmony_ci    byte!(b'0'..=b'9')(i)
14167c3a3e4Sopenharmony_ci}
14267c3a3e4Sopenharmony_ci
14367c3a3e4Sopenharmony_cifn hexadecimal(i: &[u8]) -> nom::IResult<&[u8], u8> {
14467c3a3e4Sopenharmony_ci    byte!(b'0' ..= b'9' | b'a' ..= b'f' | b'A' ..= b'F')(i)
14567c3a3e4Sopenharmony_ci}
14667c3a3e4Sopenharmony_ci
14767c3a3e4Sopenharmony_ci// ========================================
14867c3a3e4Sopenharmony_ci// ======== characters and strings ========
14967c3a3e4Sopenharmony_ci// ========================================
15067c3a3e4Sopenharmony_ci
15167c3a3e4Sopenharmony_cifn escape2char(c: char) -> CChar {
15267c3a3e4Sopenharmony_ci    CChar::Char(match c {
15367c3a3e4Sopenharmony_ci        'a' => '\x07',
15467c3a3e4Sopenharmony_ci        'b' => '\x08',
15567c3a3e4Sopenharmony_ci        'f' => '\x0c',
15667c3a3e4Sopenharmony_ci        'n' => '\n',
15767c3a3e4Sopenharmony_ci        'r' => '\r',
15867c3a3e4Sopenharmony_ci        't' => '\t',
15967c3a3e4Sopenharmony_ci        'v' => '\x0b',
16067c3a3e4Sopenharmony_ci        _ => unreachable!("invalid escape {}", c),
16167c3a3e4Sopenharmony_ci    })
16267c3a3e4Sopenharmony_ci}
16367c3a3e4Sopenharmony_ci
16467c3a3e4Sopenharmony_cifn c_raw_escape(n: Vec<u8>, radix: u32) -> Option<CChar> {
16567c3a3e4Sopenharmony_ci    str::from_utf8(&n)
16667c3a3e4Sopenharmony_ci        .ok()
16767c3a3e4Sopenharmony_ci        .and_then(|i| u64::from_str_radix(i, radix).ok())
16867c3a3e4Sopenharmony_ci        .map(|i| match i {
16967c3a3e4Sopenharmony_ci            0..=0x7f => CChar::Char(i as u8 as char),
17067c3a3e4Sopenharmony_ci            _ => CChar::Raw(i),
17167c3a3e4Sopenharmony_ci        })
17267c3a3e4Sopenharmony_ci}
17367c3a3e4Sopenharmony_ci
17467c3a3e4Sopenharmony_cifn c_unicode_escape(n: Vec<u8>) -> Option<CChar> {
17567c3a3e4Sopenharmony_ci    str::from_utf8(&n)
17667c3a3e4Sopenharmony_ci        .ok()
17767c3a3e4Sopenharmony_ci        .and_then(|i| u32::from_str_radix(i, 16).ok())
17867c3a3e4Sopenharmony_ci        .and_then(char::from_u32)
17967c3a3e4Sopenharmony_ci        .map(CChar::Char)
18067c3a3e4Sopenharmony_ci}
18167c3a3e4Sopenharmony_ci
18267c3a3e4Sopenharmony_cifn escaped_char(i: &[u8]) -> nom::IResult<&[u8], CChar> {
18367c3a3e4Sopenharmony_ci    preceded(
18467c3a3e4Sopenharmony_ci        char('\\'),
18567c3a3e4Sopenharmony_ci        alt((
18667c3a3e4Sopenharmony_ci            map(one_of(r#"'"?\"#), CChar::Char),
18767c3a3e4Sopenharmony_ci            map(one_of("abfnrtv"), escape2char),
18867c3a3e4Sopenharmony_ci            map_opt(many_m_n(1, 3, octal), |v| c_raw_escape(v, 8)),
18967c3a3e4Sopenharmony_ci            map_opt(preceded(char('x'), many1(hexadecimal)), |v| {
19067c3a3e4Sopenharmony_ci                c_raw_escape(v, 16)
19167c3a3e4Sopenharmony_ci            }),
19267c3a3e4Sopenharmony_ci            map_opt(
19367c3a3e4Sopenharmony_ci                preceded(char('u'), many_m_n(4, 4, hexadecimal)),
19467c3a3e4Sopenharmony_ci                c_unicode_escape,
19567c3a3e4Sopenharmony_ci            ),
19667c3a3e4Sopenharmony_ci            map_opt(
19767c3a3e4Sopenharmony_ci                preceded(char('U'), many_m_n(8, 8, hexadecimal)),
19867c3a3e4Sopenharmony_ci                c_unicode_escape,
19967c3a3e4Sopenharmony_ci            ),
20067c3a3e4Sopenharmony_ci        )),
20167c3a3e4Sopenharmony_ci    )(i)
20267c3a3e4Sopenharmony_ci}
20367c3a3e4Sopenharmony_ci
20467c3a3e4Sopenharmony_cifn c_width_prefix(i: &[u8]) -> nom::IResult<&[u8], &[u8]> {
20567c3a3e4Sopenharmony_ci    alt((tag("u8"), tag("u"), tag("U"), tag("L")))(i)
20667c3a3e4Sopenharmony_ci}
20767c3a3e4Sopenharmony_ci
20867c3a3e4Sopenharmony_cifn c_char(i: &[u8]) -> nom::IResult<&[u8], CChar> {
20967c3a3e4Sopenharmony_ci    delimited(
21067c3a3e4Sopenharmony_ci        terminated(opt(c_width_prefix), char('\'')),
21167c3a3e4Sopenharmony_ci        alt((
21267c3a3e4Sopenharmony_ci            escaped_char,
21367c3a3e4Sopenharmony_ci            map(byte!(0 ..= 91 /* \=92 */ | 93 ..= 255), CChar::from),
21467c3a3e4Sopenharmony_ci        )),
21567c3a3e4Sopenharmony_ci        char('\''),
21667c3a3e4Sopenharmony_ci    )(i)
21767c3a3e4Sopenharmony_ci}
21867c3a3e4Sopenharmony_ci
21967c3a3e4Sopenharmony_cifn c_string(i: &[u8]) -> nom::IResult<&[u8], Vec<u8>> {
22067c3a3e4Sopenharmony_ci    delimited(
22167c3a3e4Sopenharmony_ci        alt((preceded(c_width_prefix, char('"')), char('"'))),
22267c3a3e4Sopenharmony_ci        fold_many0(
22367c3a3e4Sopenharmony_ci            alt((
22467c3a3e4Sopenharmony_ci                map(escaped_char, |c: CChar| c.into()),
22567c3a3e4Sopenharmony_ci                map(is_not([b'\\', b'"']), |c: &[u8]| c.into()),
22667c3a3e4Sopenharmony_ci            )),
22767c3a3e4Sopenharmony_ci            Vec::new,
22867c3a3e4Sopenharmony_ci            |mut v: Vec<u8>, res: Vec<u8>| {
22967c3a3e4Sopenharmony_ci                v.extend_from_slice(&res);
23067c3a3e4Sopenharmony_ci                v
23167c3a3e4Sopenharmony_ci            },
23267c3a3e4Sopenharmony_ci        ),
23367c3a3e4Sopenharmony_ci        char('"'),
23467c3a3e4Sopenharmony_ci    )(i)
23567c3a3e4Sopenharmony_ci}
23667c3a3e4Sopenharmony_ci
23767c3a3e4Sopenharmony_ci// ================================
23867c3a3e4Sopenharmony_ci// ======== parse integers ========
23967c3a3e4Sopenharmony_ci// ================================
24067c3a3e4Sopenharmony_ci
24167c3a3e4Sopenharmony_cifn c_int_radix(n: Vec<u8>, radix: u32) -> Option<u64> {
24267c3a3e4Sopenharmony_ci    str::from_utf8(&n)
24367c3a3e4Sopenharmony_ci        .ok()
24467c3a3e4Sopenharmony_ci        .and_then(|i| u64::from_str_radix(i, radix).ok())
24567c3a3e4Sopenharmony_ci}
24667c3a3e4Sopenharmony_ci
24767c3a3e4Sopenharmony_cifn take_ul(input: &[u8]) -> IResult<&[u8], &[u8]> {
24867c3a3e4Sopenharmony_ci    let r = input.split_at_position(|c| c != b'u' && c != b'U' && c != b'l' && c != b'L');
24967c3a3e4Sopenharmony_ci    match r {
25067c3a3e4Sopenharmony_ci        Err(Err::Incomplete(_)) => Ok((&input[input.len()..], input)),
25167c3a3e4Sopenharmony_ci        res => res,
25267c3a3e4Sopenharmony_ci    }
25367c3a3e4Sopenharmony_ci}
25467c3a3e4Sopenharmony_ci
25567c3a3e4Sopenharmony_cifn c_int(i: &[u8]) -> nom::IResult<&[u8], i64> {
25667c3a3e4Sopenharmony_ci    map(
25767c3a3e4Sopenharmony_ci        terminated(
25867c3a3e4Sopenharmony_ci            alt((
25967c3a3e4Sopenharmony_ci                map_opt(preceded(tag("0x"), many1(complete(hexadecimal))), |v| {
26067c3a3e4Sopenharmony_ci                    c_int_radix(v, 16)
26167c3a3e4Sopenharmony_ci                }),
26267c3a3e4Sopenharmony_ci                map_opt(preceded(tag("0X"), many1(complete(hexadecimal))), |v| {
26367c3a3e4Sopenharmony_ci                    c_int_radix(v, 16)
26467c3a3e4Sopenharmony_ci                }),
26567c3a3e4Sopenharmony_ci                map_opt(preceded(tag("0b"), many1(complete(binary))), |v| {
26667c3a3e4Sopenharmony_ci                    c_int_radix(v, 2)
26767c3a3e4Sopenharmony_ci                }),
26867c3a3e4Sopenharmony_ci                map_opt(preceded(tag("0B"), many1(complete(binary))), |v| {
26967c3a3e4Sopenharmony_ci                    c_int_radix(v, 2)
27067c3a3e4Sopenharmony_ci                }),
27167c3a3e4Sopenharmony_ci                map_opt(preceded(char('0'), many1(complete(octal))), |v| {
27267c3a3e4Sopenharmony_ci                    c_int_radix(v, 8)
27367c3a3e4Sopenharmony_ci                }),
27467c3a3e4Sopenharmony_ci                map_opt(many1(complete(decimal)), |v| c_int_radix(v, 10)),
27567c3a3e4Sopenharmony_ci                |input| Err(crate::nom::Err::Error(nom::error::Error::new(input, crate::nom::ErrorKind::Fix))),
27667c3a3e4Sopenharmony_ci            )),
27767c3a3e4Sopenharmony_ci            opt(take_ul),
27867c3a3e4Sopenharmony_ci        ),
27967c3a3e4Sopenharmony_ci        |i| i as i64,
28067c3a3e4Sopenharmony_ci    )(i)
28167c3a3e4Sopenharmony_ci}
28267c3a3e4Sopenharmony_ci
28367c3a3e4Sopenharmony_ci// ==============================
28467c3a3e4Sopenharmony_ci// ======== parse floats ========
28567c3a3e4Sopenharmony_ci// ==============================
28667c3a3e4Sopenharmony_ci
28767c3a3e4Sopenharmony_cifn float_width(i: &[u8]) -> nom::IResult<&[u8], u8> {
28867c3a3e4Sopenharmony_ci    nom::combinator::complete(byte!(b'f' | b'l' | b'F' | b'L'))(i)
28967c3a3e4Sopenharmony_ci}
29067c3a3e4Sopenharmony_ci
29167c3a3e4Sopenharmony_cifn float_exp(i: &[u8]) -> nom::IResult<&[u8], (Option<u8>, Vec<u8>)> {
29267c3a3e4Sopenharmony_ci    preceded(
29367c3a3e4Sopenharmony_ci        byte!(b'e' | b'E'),
29467c3a3e4Sopenharmony_ci        pair(opt(byte!(b'-' | b'+')), many1(complete(decimal))),
29567c3a3e4Sopenharmony_ci    )(i)
29667c3a3e4Sopenharmony_ci}
29767c3a3e4Sopenharmony_ci
29867c3a3e4Sopenharmony_cifn c_float(i: &[u8]) -> nom::IResult<&[u8], f64> {
29967c3a3e4Sopenharmony_ci    map_opt(
30067c3a3e4Sopenharmony_ci        alt((
30167c3a3e4Sopenharmony_ci            terminated(
30267c3a3e4Sopenharmony_ci                recognize(tuple((
30367c3a3e4Sopenharmony_ci                    many1(complete(decimal)),
30467c3a3e4Sopenharmony_ci                    byte!(b'.'),
30567c3a3e4Sopenharmony_ci                    many0(complete(decimal)),
30667c3a3e4Sopenharmony_ci                ))),
30767c3a3e4Sopenharmony_ci                opt(float_width),
30867c3a3e4Sopenharmony_ci            ),
30967c3a3e4Sopenharmony_ci            terminated(
31067c3a3e4Sopenharmony_ci                recognize(tuple((
31167c3a3e4Sopenharmony_ci                    many0(complete(decimal)),
31267c3a3e4Sopenharmony_ci                    byte!(b'.'),
31367c3a3e4Sopenharmony_ci                    many1(complete(decimal)),
31467c3a3e4Sopenharmony_ci                ))),
31567c3a3e4Sopenharmony_ci                opt(float_width),
31667c3a3e4Sopenharmony_ci            ),
31767c3a3e4Sopenharmony_ci            terminated(
31867c3a3e4Sopenharmony_ci                recognize(tuple((
31967c3a3e4Sopenharmony_ci                    many0(complete(decimal)),
32067c3a3e4Sopenharmony_ci                    opt(byte!(b'.')),
32167c3a3e4Sopenharmony_ci                    many1(complete(decimal)),
32267c3a3e4Sopenharmony_ci                    float_exp,
32367c3a3e4Sopenharmony_ci                ))),
32467c3a3e4Sopenharmony_ci                opt(float_width),
32567c3a3e4Sopenharmony_ci            ),
32667c3a3e4Sopenharmony_ci            terminated(
32767c3a3e4Sopenharmony_ci                recognize(tuple((
32867c3a3e4Sopenharmony_ci                    many1(complete(decimal)),
32967c3a3e4Sopenharmony_ci                    opt(byte!(b'.')),
33067c3a3e4Sopenharmony_ci                    many0(complete(decimal)),
33167c3a3e4Sopenharmony_ci                    float_exp,
33267c3a3e4Sopenharmony_ci                ))),
33367c3a3e4Sopenharmony_ci                opt(float_width),
33467c3a3e4Sopenharmony_ci            ),
33567c3a3e4Sopenharmony_ci            terminated(recognize(many1(complete(decimal))), float_width),
33667c3a3e4Sopenharmony_ci        )),
33767c3a3e4Sopenharmony_ci        |v| str::from_utf8(v).ok().and_then(|i| f64::from_str(i).ok()),
33867c3a3e4Sopenharmony_ci    )(i)
33967c3a3e4Sopenharmony_ci}
34067c3a3e4Sopenharmony_ci
34167c3a3e4Sopenharmony_ci// ================================
34267c3a3e4Sopenharmony_ci// ======== main interface ========
34367c3a3e4Sopenharmony_ci// ================================
34467c3a3e4Sopenharmony_ci
34567c3a3e4Sopenharmony_cifn one_literal(input: &[u8]) -> nom::IResult<&[u8], EvalResult, crate::Error<&[u8]>> {
34667c3a3e4Sopenharmony_ci    alt((
34767c3a3e4Sopenharmony_ci        map(full(c_char), EvalResult::Char),
34867c3a3e4Sopenharmony_ci        map(full(c_int), |i| EvalResult::Int(::std::num::Wrapping(i))),
34967c3a3e4Sopenharmony_ci        map(full(c_float), EvalResult::Float),
35067c3a3e4Sopenharmony_ci        map(full(c_string), EvalResult::Str),
35167c3a3e4Sopenharmony_ci    ))(input)
35267c3a3e4Sopenharmony_ci    .to_cexpr_result()
35367c3a3e4Sopenharmony_ci}
35467c3a3e4Sopenharmony_ci
35567c3a3e4Sopenharmony_ci/// Parse a C literal.
35667c3a3e4Sopenharmony_ci///
35767c3a3e4Sopenharmony_ci/// The input must contain exactly the representation of a single literal
35867c3a3e4Sopenharmony_ci/// token, and in particular no whitespace or sign prefixes.
35967c3a3e4Sopenharmony_cipub fn parse(input: &[u8]) -> IResult<&[u8], EvalResult, crate::Error<&[u8]>> {
36067c3a3e4Sopenharmony_ci    crate::assert_full_parse(one_literal(input))
36167c3a3e4Sopenharmony_ci}
362