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//! Evaluating C expressions from tokens.
967c3a3e4Sopenharmony_ci//!
1067c3a3e4Sopenharmony_ci//! Numerical operators are supported. All numerical values are treated as
1167c3a3e4Sopenharmony_ci//! `i64` or `f64`. Type casting is not supported. `i64` are converted to
1267c3a3e4Sopenharmony_ci//! `f64` when used in conjunction with a `f64`. Right shifts are always
1367c3a3e4Sopenharmony_ci//! arithmetic shifts.
1467c3a3e4Sopenharmony_ci//!
1567c3a3e4Sopenharmony_ci//! The `sizeof` operator is not supported.
1667c3a3e4Sopenharmony_ci//!
1767c3a3e4Sopenharmony_ci//! String concatenation is supported, but width prefixes are ignored; all
1867c3a3e4Sopenharmony_ci//! strings are treated as narrow strings.
1967c3a3e4Sopenharmony_ci//!
2067c3a3e4Sopenharmony_ci//! Use the `IdentifierParser` to substitute identifiers found in expressions.
2167c3a3e4Sopenharmony_ci
2267c3a3e4Sopenharmony_ciuse std::collections::HashMap;
2367c3a3e4Sopenharmony_ciuse std::num::Wrapping;
2467c3a3e4Sopenharmony_ciuse std::ops::{
2567c3a3e4Sopenharmony_ci    AddAssign, BitAndAssign, BitOrAssign, BitXorAssign, DivAssign, MulAssign, RemAssign, ShlAssign,
2667c3a3e4Sopenharmony_ci    ShrAssign, SubAssign,
2767c3a3e4Sopenharmony_ci};
2867c3a3e4Sopenharmony_ci
2967c3a3e4Sopenharmony_ciuse crate::literal::{self, CChar};
3067c3a3e4Sopenharmony_ciuse crate::token::{Kind as TokenKind, Token};
3167c3a3e4Sopenharmony_ciuse crate::ToCexprResult;
3267c3a3e4Sopenharmony_ciuse nom::branch::alt;
3367c3a3e4Sopenharmony_ciuse nom::combinator::{complete, map, map_opt};
3467c3a3e4Sopenharmony_ciuse nom::multi::{fold_many0, many0, separated_list0};
3567c3a3e4Sopenharmony_ciuse nom::sequence::{delimited, pair, preceded};
3667c3a3e4Sopenharmony_ciuse nom::*;
3767c3a3e4Sopenharmony_ci
3867c3a3e4Sopenharmony_ci/// Expression parser/evaluator that supports identifiers.
3967c3a3e4Sopenharmony_ci#[derive(Debug)]
4067c3a3e4Sopenharmony_cipub struct IdentifierParser<'ident> {
4167c3a3e4Sopenharmony_ci    identifiers: &'ident HashMap<Vec<u8>, EvalResult>,
4267c3a3e4Sopenharmony_ci}
4367c3a3e4Sopenharmony_ci#[derive(Copy, Clone)]
4467c3a3e4Sopenharmony_cistruct PRef<'a>(&'a IdentifierParser<'a>);
4567c3a3e4Sopenharmony_ci
4667c3a3e4Sopenharmony_ci/// A shorthand for the type of cexpr expression evaluation results.
4767c3a3e4Sopenharmony_cipub type CResult<'a, R> = IResult<&'a [Token], R, crate::Error<&'a [Token]>>;
4867c3a3e4Sopenharmony_ci
4967c3a3e4Sopenharmony_ci/// The result of parsing a literal or evaluating an expression.
5067c3a3e4Sopenharmony_ci#[derive(Debug, Clone, PartialEq)]
5167c3a3e4Sopenharmony_ci#[allow(missing_docs)]
5267c3a3e4Sopenharmony_cipub enum EvalResult {
5367c3a3e4Sopenharmony_ci    Int(Wrapping<i64>),
5467c3a3e4Sopenharmony_ci    Float(f64),
5567c3a3e4Sopenharmony_ci    Char(CChar),
5667c3a3e4Sopenharmony_ci    Str(Vec<u8>),
5767c3a3e4Sopenharmony_ci    Invalid,
5867c3a3e4Sopenharmony_ci}
5967c3a3e4Sopenharmony_ci
6067c3a3e4Sopenharmony_cimacro_rules! result_opt (
6167c3a3e4Sopenharmony_ci	(fn $n:ident: $e:ident -> $t:ty) => (
6267c3a3e4Sopenharmony_ci		#[allow(dead_code)]
6367c3a3e4Sopenharmony_ci        #[allow(clippy::wrong_self_convention)]
6467c3a3e4Sopenharmony_ci		fn $n(self) -> Option<$t> {
6567c3a3e4Sopenharmony_ci			if let EvalResult::$e(v) = self {
6667c3a3e4Sopenharmony_ci				Some(v)
6767c3a3e4Sopenharmony_ci			} else {
6867c3a3e4Sopenharmony_ci				None
6967c3a3e4Sopenharmony_ci			}
7067c3a3e4Sopenharmony_ci		}
7167c3a3e4Sopenharmony_ci	);
7267c3a3e4Sopenharmony_ci);
7367c3a3e4Sopenharmony_ci
7467c3a3e4Sopenharmony_ciimpl EvalResult {
7567c3a3e4Sopenharmony_ci    result_opt!(fn as_int: Int -> Wrapping<i64>);
7667c3a3e4Sopenharmony_ci    result_opt!(fn as_float: Float -> f64);
7767c3a3e4Sopenharmony_ci    result_opt!(fn as_char: Char -> CChar);
7867c3a3e4Sopenharmony_ci    result_opt!(fn as_str: Str -> Vec<u8>);
7967c3a3e4Sopenharmony_ci
8067c3a3e4Sopenharmony_ci    #[allow(clippy::wrong_self_convention)]
8167c3a3e4Sopenharmony_ci    fn as_numeric(self) -> Option<EvalResult> {
8267c3a3e4Sopenharmony_ci        match self {
8367c3a3e4Sopenharmony_ci            EvalResult::Int(_) | EvalResult::Float(_) => Some(self),
8467c3a3e4Sopenharmony_ci            _ => None,
8567c3a3e4Sopenharmony_ci        }
8667c3a3e4Sopenharmony_ci    }
8767c3a3e4Sopenharmony_ci}
8867c3a3e4Sopenharmony_ci
8967c3a3e4Sopenharmony_ciimpl From<Vec<u8>> for EvalResult {
9067c3a3e4Sopenharmony_ci    fn from(s: Vec<u8>) -> EvalResult {
9167c3a3e4Sopenharmony_ci        EvalResult::Str(s)
9267c3a3e4Sopenharmony_ci    }
9367c3a3e4Sopenharmony_ci}
9467c3a3e4Sopenharmony_ci
9567c3a3e4Sopenharmony_ci// ===========================================
9667c3a3e4Sopenharmony_ci// ============= Clang tokens ================
9767c3a3e4Sopenharmony_ci// ===========================================
9867c3a3e4Sopenharmony_ci
9967c3a3e4Sopenharmony_cimacro_rules! exact_token (
10067c3a3e4Sopenharmony_ci	($k:ident, $c:expr) => ({
10167c3a3e4Sopenharmony_ci        move |input: &[Token]| {
10267c3a3e4Sopenharmony_ci		if input.is_empty() {
10367c3a3e4Sopenharmony_ci			let res: CResult<'_, &[u8]> = Err(crate::nom::Err::Incomplete(Needed::new($c.len())));
10467c3a3e4Sopenharmony_ci			res
10567c3a3e4Sopenharmony_ci		} else {
10667c3a3e4Sopenharmony_ci			if input[0].kind==TokenKind::$k && &input[0].raw[..]==$c {
10767c3a3e4Sopenharmony_ci				Ok((&input[1..], &input[0].raw[..]))
10867c3a3e4Sopenharmony_ci			} else {
10967c3a3e4Sopenharmony_ci				Err(crate::nom::Err::Error((input, crate::ErrorKind::ExactToken(TokenKind::$k,$c)).into()))
11067c3a3e4Sopenharmony_ci			}
11167c3a3e4Sopenharmony_ci		}
11267c3a3e4Sopenharmony_ci        }
11367c3a3e4Sopenharmony_ci	});
11467c3a3e4Sopenharmony_ci);
11567c3a3e4Sopenharmony_ci
11667c3a3e4Sopenharmony_cifn identifier_token(input: &[Token]) -> CResult<'_, &[u8]> {
11767c3a3e4Sopenharmony_ci    if input.is_empty() {
11867c3a3e4Sopenharmony_ci        let res: CResult<'_, &[u8]> = Err(nom::Err::Incomplete(Needed::new(1)));
11967c3a3e4Sopenharmony_ci        res
12067c3a3e4Sopenharmony_ci    } else {
12167c3a3e4Sopenharmony_ci        if input[0].kind == TokenKind::Identifier {
12267c3a3e4Sopenharmony_ci            Ok((&input[1..], &input[0].raw[..]))
12367c3a3e4Sopenharmony_ci        } else {
12467c3a3e4Sopenharmony_ci            Err(crate::nom::Err::Error((input, crate::ErrorKind::TypedToken(TokenKind::Identifier)).into()))
12567c3a3e4Sopenharmony_ci        }
12667c3a3e4Sopenharmony_ci    }
12767c3a3e4Sopenharmony_ci}
12867c3a3e4Sopenharmony_ci
12967c3a3e4Sopenharmony_cifn p(c: &'static str) -> impl Fn(&[Token]) -> CResult<'_, &[u8]> {
13067c3a3e4Sopenharmony_ci    exact_token!(Punctuation, c.as_bytes())
13167c3a3e4Sopenharmony_ci}
13267c3a3e4Sopenharmony_ci
13367c3a3e4Sopenharmony_cifn one_of_punctuation(c: &'static [&'static str]) -> impl Fn(&[Token]) -> CResult<'_, &[u8]> {
13467c3a3e4Sopenharmony_ci    move |input| {
13567c3a3e4Sopenharmony_ci        if input.is_empty() {
13667c3a3e4Sopenharmony_ci            let min = c
13767c3a3e4Sopenharmony_ci                .iter()
13867c3a3e4Sopenharmony_ci                .map(|opt| opt.len())
13967c3a3e4Sopenharmony_ci                .min()
14067c3a3e4Sopenharmony_ci                .expect("at least one option");
14167c3a3e4Sopenharmony_ci            Err(crate::nom::Err::Incomplete(Needed::new(min)))
14267c3a3e4Sopenharmony_ci        } else if input[0].kind == TokenKind::Punctuation
14367c3a3e4Sopenharmony_ci            && c.iter().any(|opt| opt.as_bytes() == &input[0].raw[..])
14467c3a3e4Sopenharmony_ci        {
14567c3a3e4Sopenharmony_ci            Ok((&input[1..], &input[0].raw[..]))
14667c3a3e4Sopenharmony_ci        } else {
14767c3a3e4Sopenharmony_ci            Err(crate::nom::Err::Error(
14867c3a3e4Sopenharmony_ci                (
14967c3a3e4Sopenharmony_ci                    input,
15067c3a3e4Sopenharmony_ci                    crate::ErrorKind::ExactTokens(TokenKind::Punctuation, c),
15167c3a3e4Sopenharmony_ci                )
15267c3a3e4Sopenharmony_ci                    .into(),
15367c3a3e4Sopenharmony_ci            ))
15467c3a3e4Sopenharmony_ci        }
15567c3a3e4Sopenharmony_ci    }
15667c3a3e4Sopenharmony_ci}
15767c3a3e4Sopenharmony_ci
15867c3a3e4Sopenharmony_ci// ==================================================
15967c3a3e4Sopenharmony_ci// ============= Numeric expressions ================
16067c3a3e4Sopenharmony_ci// ==================================================
16167c3a3e4Sopenharmony_ci
16267c3a3e4Sopenharmony_ciimpl<'a> AddAssign<&'a EvalResult> for EvalResult {
16367c3a3e4Sopenharmony_ci    fn add_assign(&mut self, rhs: &'a EvalResult) {
16467c3a3e4Sopenharmony_ci        use self::EvalResult::*;
16567c3a3e4Sopenharmony_ci        *self = match (&*self, rhs) {
16667c3a3e4Sopenharmony_ci            (&Int(a), &Int(b)) => Int(a + b),
16767c3a3e4Sopenharmony_ci            (&Float(a), &Int(b)) => Float(a + (b.0 as f64)),
16867c3a3e4Sopenharmony_ci            (&Int(a), &Float(b)) => Float(a.0 as f64 + b),
16967c3a3e4Sopenharmony_ci            (&Float(a), &Float(b)) => Float(a + b),
17067c3a3e4Sopenharmony_ci            _ => Invalid,
17167c3a3e4Sopenharmony_ci        };
17267c3a3e4Sopenharmony_ci    }
17367c3a3e4Sopenharmony_ci}
17467c3a3e4Sopenharmony_ciimpl<'a> BitAndAssign<&'a EvalResult> for EvalResult {
17567c3a3e4Sopenharmony_ci    fn bitand_assign(&mut self, rhs: &'a EvalResult) {
17667c3a3e4Sopenharmony_ci        use self::EvalResult::*;
17767c3a3e4Sopenharmony_ci        *self = match (&*self, rhs) {
17867c3a3e4Sopenharmony_ci            (&Int(a), &Int(b)) => Int(a & b),
17967c3a3e4Sopenharmony_ci            _ => Invalid,
18067c3a3e4Sopenharmony_ci        };
18167c3a3e4Sopenharmony_ci    }
18267c3a3e4Sopenharmony_ci}
18367c3a3e4Sopenharmony_ciimpl<'a> BitOrAssign<&'a EvalResult> for EvalResult {
18467c3a3e4Sopenharmony_ci    fn bitor_assign(&mut self, rhs: &'a EvalResult) {
18567c3a3e4Sopenharmony_ci        use self::EvalResult::*;
18667c3a3e4Sopenharmony_ci        *self = match (&*self, rhs) {
18767c3a3e4Sopenharmony_ci            (&Int(a), &Int(b)) => Int(a | b),
18867c3a3e4Sopenharmony_ci            _ => Invalid,
18967c3a3e4Sopenharmony_ci        };
19067c3a3e4Sopenharmony_ci    }
19167c3a3e4Sopenharmony_ci}
19267c3a3e4Sopenharmony_ciimpl<'a> BitXorAssign<&'a EvalResult> for EvalResult {
19367c3a3e4Sopenharmony_ci    fn bitxor_assign(&mut self, rhs: &'a EvalResult) {
19467c3a3e4Sopenharmony_ci        use self::EvalResult::*;
19567c3a3e4Sopenharmony_ci        *self = match (&*self, rhs) {
19667c3a3e4Sopenharmony_ci            (&Int(a), &Int(b)) => Int(a ^ b),
19767c3a3e4Sopenharmony_ci            _ => Invalid,
19867c3a3e4Sopenharmony_ci        };
19967c3a3e4Sopenharmony_ci    }
20067c3a3e4Sopenharmony_ci}
20167c3a3e4Sopenharmony_ciimpl<'a> DivAssign<&'a EvalResult> for EvalResult {
20267c3a3e4Sopenharmony_ci    fn div_assign(&mut self, rhs: &'a EvalResult) {
20367c3a3e4Sopenharmony_ci        use self::EvalResult::*;
20467c3a3e4Sopenharmony_ci        *self = match (&*self, rhs) {
20567c3a3e4Sopenharmony_ci            (&Int(a), &Int(b)) => Int(a / b),
20667c3a3e4Sopenharmony_ci            (&Float(a), &Int(b)) => Float(a / (b.0 as f64)),
20767c3a3e4Sopenharmony_ci            (&Int(a), &Float(b)) => Float(a.0 as f64 / b),
20867c3a3e4Sopenharmony_ci            (&Float(a), &Float(b)) => Float(a / b),
20967c3a3e4Sopenharmony_ci            _ => Invalid,
21067c3a3e4Sopenharmony_ci        };
21167c3a3e4Sopenharmony_ci    }
21267c3a3e4Sopenharmony_ci}
21367c3a3e4Sopenharmony_ciimpl<'a> MulAssign<&'a EvalResult> for EvalResult {
21467c3a3e4Sopenharmony_ci    fn mul_assign(&mut self, rhs: &'a EvalResult) {
21567c3a3e4Sopenharmony_ci        use self::EvalResult::*;
21667c3a3e4Sopenharmony_ci        *self = match (&*self, rhs) {
21767c3a3e4Sopenharmony_ci            (&Int(a), &Int(b)) => Int(a * b),
21867c3a3e4Sopenharmony_ci            (&Float(a), &Int(b)) => Float(a * (b.0 as f64)),
21967c3a3e4Sopenharmony_ci            (&Int(a), &Float(b)) => Float(a.0 as f64 * b),
22067c3a3e4Sopenharmony_ci            (&Float(a), &Float(b)) => Float(a * b),
22167c3a3e4Sopenharmony_ci            _ => Invalid,
22267c3a3e4Sopenharmony_ci        };
22367c3a3e4Sopenharmony_ci    }
22467c3a3e4Sopenharmony_ci}
22567c3a3e4Sopenharmony_ciimpl<'a> RemAssign<&'a EvalResult> for EvalResult {
22667c3a3e4Sopenharmony_ci    fn rem_assign(&mut self, rhs: &'a EvalResult) {
22767c3a3e4Sopenharmony_ci        use self::EvalResult::*;
22867c3a3e4Sopenharmony_ci        *self = match (&*self, rhs) {
22967c3a3e4Sopenharmony_ci            (&Int(a), &Int(b)) => Int(a % b),
23067c3a3e4Sopenharmony_ci            (&Float(a), &Int(b)) => Float(a % (b.0 as f64)),
23167c3a3e4Sopenharmony_ci            (&Int(a), &Float(b)) => Float(a.0 as f64 % b),
23267c3a3e4Sopenharmony_ci            (&Float(a), &Float(b)) => Float(a % b),
23367c3a3e4Sopenharmony_ci            _ => Invalid,
23467c3a3e4Sopenharmony_ci        };
23567c3a3e4Sopenharmony_ci    }
23667c3a3e4Sopenharmony_ci}
23767c3a3e4Sopenharmony_ciimpl<'a> ShlAssign<&'a EvalResult> for EvalResult {
23867c3a3e4Sopenharmony_ci    fn shl_assign(&mut self, rhs: &'a EvalResult) {
23967c3a3e4Sopenharmony_ci        use self::EvalResult::*;
24067c3a3e4Sopenharmony_ci        *self = match (&*self, rhs) {
24167c3a3e4Sopenharmony_ci            (&Int(a), &Int(b)) => Int(a << (b.0 as usize)),
24267c3a3e4Sopenharmony_ci            _ => Invalid,
24367c3a3e4Sopenharmony_ci        };
24467c3a3e4Sopenharmony_ci    }
24567c3a3e4Sopenharmony_ci}
24667c3a3e4Sopenharmony_ciimpl<'a> ShrAssign<&'a EvalResult> for EvalResult {
24767c3a3e4Sopenharmony_ci    fn shr_assign(&mut self, rhs: &'a EvalResult) {
24867c3a3e4Sopenharmony_ci        use self::EvalResult::*;
24967c3a3e4Sopenharmony_ci        *self = match (&*self, rhs) {
25067c3a3e4Sopenharmony_ci            (&Int(a), &Int(b)) => Int(a >> (b.0 as usize)),
25167c3a3e4Sopenharmony_ci            _ => Invalid,
25267c3a3e4Sopenharmony_ci        };
25367c3a3e4Sopenharmony_ci    }
25467c3a3e4Sopenharmony_ci}
25567c3a3e4Sopenharmony_ciimpl<'a> SubAssign<&'a EvalResult> for EvalResult {
25667c3a3e4Sopenharmony_ci    fn sub_assign(&mut self, rhs: &'a EvalResult) {
25767c3a3e4Sopenharmony_ci        use self::EvalResult::*;
25867c3a3e4Sopenharmony_ci        *self = match (&*self, rhs) {
25967c3a3e4Sopenharmony_ci            (&Int(a), &Int(b)) => Int(a - b),
26067c3a3e4Sopenharmony_ci            (&Float(a), &Int(b)) => Float(a - (b.0 as f64)),
26167c3a3e4Sopenharmony_ci            (&Int(a), &Float(b)) => Float(a.0 as f64 - b),
26267c3a3e4Sopenharmony_ci            (&Float(a), &Float(b)) => Float(a - b),
26367c3a3e4Sopenharmony_ci            _ => Invalid,
26467c3a3e4Sopenharmony_ci        };
26567c3a3e4Sopenharmony_ci    }
26667c3a3e4Sopenharmony_ci}
26767c3a3e4Sopenharmony_ci
26867c3a3e4Sopenharmony_cifn unary_op(input: (&[u8], EvalResult)) -> Option<EvalResult> {
26967c3a3e4Sopenharmony_ci    use self::EvalResult::*;
27067c3a3e4Sopenharmony_ci    assert_eq!(input.0.len(), 1);
27167c3a3e4Sopenharmony_ci    match (input.0[0], input.1) {
27267c3a3e4Sopenharmony_ci        (b'+', i) => Some(i),
27367c3a3e4Sopenharmony_ci        (b'-', Int(i)) => Some(Int(Wrapping(i.0.wrapping_neg()))), // impl Neg for Wrapping not until rust 1.10...
27467c3a3e4Sopenharmony_ci        (b'-', Float(i)) => Some(Float(-i)),
27567c3a3e4Sopenharmony_ci        (b'-', _) => unreachable!("non-numeric unary op"),
27667c3a3e4Sopenharmony_ci        (b'~', Int(i)) => Some(Int(!i)),
27767c3a3e4Sopenharmony_ci        (b'~', Float(_)) => None,
27867c3a3e4Sopenharmony_ci        (b'~', _) => unreachable!("non-numeric unary op"),
27967c3a3e4Sopenharmony_ci        _ => unreachable!("invalid unary op"),
28067c3a3e4Sopenharmony_ci    }
28167c3a3e4Sopenharmony_ci}
28267c3a3e4Sopenharmony_ci
28367c3a3e4Sopenharmony_cifn numeric<I: Clone, E: nom::error::ParseError<I>, F>(
28467c3a3e4Sopenharmony_ci    f: F,
28567c3a3e4Sopenharmony_ci) -> impl FnMut(I) -> nom::IResult<I, EvalResult, E>
28667c3a3e4Sopenharmony_ciwhere
28767c3a3e4Sopenharmony_ci    F: FnMut(I) -> nom::IResult<I, EvalResult, E>,
28867c3a3e4Sopenharmony_ci{
28967c3a3e4Sopenharmony_ci    nom::combinator::map_opt(f, EvalResult::as_numeric)
29067c3a3e4Sopenharmony_ci}
29167c3a3e4Sopenharmony_ci
29267c3a3e4Sopenharmony_ciimpl<'a> PRef<'a> {
29367c3a3e4Sopenharmony_ci    fn unary(self, input: &'_ [Token]) -> CResult<'_, EvalResult> {
29467c3a3e4Sopenharmony_ci        alt((
29567c3a3e4Sopenharmony_ci            delimited(p("("), |i| self.numeric_expr(i), p(")")),
29667c3a3e4Sopenharmony_ci            numeric(|i| self.literal(i)),
29767c3a3e4Sopenharmony_ci            numeric(|i| self.identifier(i)),
29867c3a3e4Sopenharmony_ci            map_opt(
29967c3a3e4Sopenharmony_ci                pair(one_of_punctuation(&["+", "-", "~"][..]), |i| self.unary(i)),
30067c3a3e4Sopenharmony_ci                unary_op,
30167c3a3e4Sopenharmony_ci            ),
30267c3a3e4Sopenharmony_ci        ))(input)
30367c3a3e4Sopenharmony_ci    }
30467c3a3e4Sopenharmony_ci
30567c3a3e4Sopenharmony_ci    fn mul_div_rem(self, input: &'_ [Token]) -> CResult<'_, EvalResult> {
30667c3a3e4Sopenharmony_ci        let (input, acc) = self.unary(input)?;
30767c3a3e4Sopenharmony_ci        fold_many0(
30867c3a3e4Sopenharmony_ci            pair(complete(one_of_punctuation(&["*", "/", "%"][..])), |i| {
30967c3a3e4Sopenharmony_ci                self.unary(i)
31067c3a3e4Sopenharmony_ci            }),
31167c3a3e4Sopenharmony_ci            move || acc.clone(),
31267c3a3e4Sopenharmony_ci            |mut acc, (op, val): (&[u8], EvalResult)| {
31367c3a3e4Sopenharmony_ci                match op[0] as char {
31467c3a3e4Sopenharmony_ci                    '*' => acc *= &val,
31567c3a3e4Sopenharmony_ci                    '/' => acc /= &val,
31667c3a3e4Sopenharmony_ci                    '%' => acc %= &val,
31767c3a3e4Sopenharmony_ci                    _ => unreachable!(),
31867c3a3e4Sopenharmony_ci                };
31967c3a3e4Sopenharmony_ci                acc
32067c3a3e4Sopenharmony_ci            },
32167c3a3e4Sopenharmony_ci        )(input)
32267c3a3e4Sopenharmony_ci    }
32367c3a3e4Sopenharmony_ci
32467c3a3e4Sopenharmony_ci    fn add_sub(self, input: &'_ [Token]) -> CResult<'_, EvalResult> {
32567c3a3e4Sopenharmony_ci        let (input, acc) = self.mul_div_rem(input)?;
32667c3a3e4Sopenharmony_ci        fold_many0(
32767c3a3e4Sopenharmony_ci            pair(complete(one_of_punctuation(&["+", "-"][..])), |i| {
32867c3a3e4Sopenharmony_ci                self.mul_div_rem(i)
32967c3a3e4Sopenharmony_ci            }),
33067c3a3e4Sopenharmony_ci            move || acc.clone(),
33167c3a3e4Sopenharmony_ci            |mut acc, (op, val): (&[u8], EvalResult)| {
33267c3a3e4Sopenharmony_ci                match op[0] as char {
33367c3a3e4Sopenharmony_ci                    '+' => acc += &val,
33467c3a3e4Sopenharmony_ci                    '-' => acc -= &val,
33567c3a3e4Sopenharmony_ci                    _ => unreachable!(),
33667c3a3e4Sopenharmony_ci                };
33767c3a3e4Sopenharmony_ci                acc
33867c3a3e4Sopenharmony_ci            },
33967c3a3e4Sopenharmony_ci        )(input)
34067c3a3e4Sopenharmony_ci    }
34167c3a3e4Sopenharmony_ci
34267c3a3e4Sopenharmony_ci    fn shl_shr(self, input: &'_ [Token]) -> CResult<'_, EvalResult> {
34367c3a3e4Sopenharmony_ci        let (input, acc) = self.add_sub(input)?;
34467c3a3e4Sopenharmony_ci        numeric(fold_many0(
34567c3a3e4Sopenharmony_ci            pair(complete(one_of_punctuation(&["<<", ">>"][..])), |i| {
34667c3a3e4Sopenharmony_ci                self.add_sub(i)
34767c3a3e4Sopenharmony_ci            }),
34867c3a3e4Sopenharmony_ci            move || acc.clone(),
34967c3a3e4Sopenharmony_ci            |mut acc, (op, val): (&[u8], EvalResult)| {
35067c3a3e4Sopenharmony_ci                match op {
35167c3a3e4Sopenharmony_ci                    b"<<" => acc <<= &val,
35267c3a3e4Sopenharmony_ci                    b">>" => acc >>= &val,
35367c3a3e4Sopenharmony_ci                    _ => unreachable!(),
35467c3a3e4Sopenharmony_ci                };
35567c3a3e4Sopenharmony_ci                acc
35667c3a3e4Sopenharmony_ci            },
35767c3a3e4Sopenharmony_ci        ))(input)
35867c3a3e4Sopenharmony_ci    }
35967c3a3e4Sopenharmony_ci
36067c3a3e4Sopenharmony_ci    fn and(self, input: &'_ [Token]) -> CResult<'_, EvalResult> {
36167c3a3e4Sopenharmony_ci        let (input, acc) = self.shl_shr(input)?;
36267c3a3e4Sopenharmony_ci        numeric(fold_many0(
36367c3a3e4Sopenharmony_ci            preceded(complete(p("&")), |i| self.shl_shr(i)),
36467c3a3e4Sopenharmony_ci            move || acc.clone(),
36567c3a3e4Sopenharmony_ci            |mut acc, val: EvalResult| {
36667c3a3e4Sopenharmony_ci                acc &= &val;
36767c3a3e4Sopenharmony_ci                acc
36867c3a3e4Sopenharmony_ci            },
36967c3a3e4Sopenharmony_ci        ))(input)
37067c3a3e4Sopenharmony_ci    }
37167c3a3e4Sopenharmony_ci
37267c3a3e4Sopenharmony_ci    fn xor(self, input: &'_ [Token]) -> CResult<'_, EvalResult> {
37367c3a3e4Sopenharmony_ci        let (input, acc) = self.and(input)?;
37467c3a3e4Sopenharmony_ci        numeric(fold_many0(
37567c3a3e4Sopenharmony_ci            preceded(complete(p("^")), |i| self.and(i)),
37667c3a3e4Sopenharmony_ci            move || acc.clone(),
37767c3a3e4Sopenharmony_ci            |mut acc, val: EvalResult| {
37867c3a3e4Sopenharmony_ci                acc ^= &val;
37967c3a3e4Sopenharmony_ci                acc
38067c3a3e4Sopenharmony_ci            },
38167c3a3e4Sopenharmony_ci        ))(input)
38267c3a3e4Sopenharmony_ci    }
38367c3a3e4Sopenharmony_ci
38467c3a3e4Sopenharmony_ci    fn or(self, input: &'_ [Token]) -> CResult<'_, EvalResult> {
38567c3a3e4Sopenharmony_ci        let (input, acc) = self.xor(input)?;
38667c3a3e4Sopenharmony_ci        numeric(fold_many0(
38767c3a3e4Sopenharmony_ci            preceded(complete(p("|")), |i| self.xor(i)),
38867c3a3e4Sopenharmony_ci            move || acc.clone(),
38967c3a3e4Sopenharmony_ci            |mut acc, val: EvalResult| {
39067c3a3e4Sopenharmony_ci                acc |= &val;
39167c3a3e4Sopenharmony_ci                acc
39267c3a3e4Sopenharmony_ci            },
39367c3a3e4Sopenharmony_ci        ))(input)
39467c3a3e4Sopenharmony_ci    }
39567c3a3e4Sopenharmony_ci
39667c3a3e4Sopenharmony_ci    #[inline(always)]
39767c3a3e4Sopenharmony_ci    fn numeric_expr(self, input: &'_ [Token]) -> CResult<'_, EvalResult> {
39867c3a3e4Sopenharmony_ci        self.or(input)
39967c3a3e4Sopenharmony_ci    }
40067c3a3e4Sopenharmony_ci}
40167c3a3e4Sopenharmony_ci
40267c3a3e4Sopenharmony_ci// =======================================================
40367c3a3e4Sopenharmony_ci// ============= Literals and identifiers ================
40467c3a3e4Sopenharmony_ci// =======================================================
40567c3a3e4Sopenharmony_ci
40667c3a3e4Sopenharmony_ciimpl<'a> PRef<'a> {
40767c3a3e4Sopenharmony_ci    fn identifier(self, input: &'_ [Token]) -> CResult<'_, EvalResult> {
40867c3a3e4Sopenharmony_ci        match input.split_first() {
40967c3a3e4Sopenharmony_ci            None => Err(Err::Incomplete(Needed::new(1))),
41067c3a3e4Sopenharmony_ci            Some((
41167c3a3e4Sopenharmony_ci                &Token {
41267c3a3e4Sopenharmony_ci                    kind: TokenKind::Identifier,
41367c3a3e4Sopenharmony_ci                    ref raw,
41467c3a3e4Sopenharmony_ci                },
41567c3a3e4Sopenharmony_ci                rest,
41667c3a3e4Sopenharmony_ci            )) => {
41767c3a3e4Sopenharmony_ci                if let Some(r) = self.identifiers.get(&raw[..]) {
41867c3a3e4Sopenharmony_ci                    Ok((rest, r.clone()))
41967c3a3e4Sopenharmony_ci                } else {
42067c3a3e4Sopenharmony_ci                    Err(Err::Error(
42167c3a3e4Sopenharmony_ci                        (input, crate::ErrorKind::UnknownIdentifier).into(),
42267c3a3e4Sopenharmony_ci                    ))
42367c3a3e4Sopenharmony_ci                }
42467c3a3e4Sopenharmony_ci            }
42567c3a3e4Sopenharmony_ci            Some(_) => Err(Err::Error(
42667c3a3e4Sopenharmony_ci                (input, crate::ErrorKind::TypedToken(TokenKind::Identifier)).into(),
42767c3a3e4Sopenharmony_ci            )),
42867c3a3e4Sopenharmony_ci        }
42967c3a3e4Sopenharmony_ci    }
43067c3a3e4Sopenharmony_ci
43167c3a3e4Sopenharmony_ci    fn literal(self, input: &'_ [Token]) -> CResult<'_, EvalResult> {
43267c3a3e4Sopenharmony_ci        match input.split_first() {
43367c3a3e4Sopenharmony_ci            None => Err(Err::Incomplete(Needed::new(1))),
43467c3a3e4Sopenharmony_ci            Some((
43567c3a3e4Sopenharmony_ci                &Token {
43667c3a3e4Sopenharmony_ci                    kind: TokenKind::Literal,
43767c3a3e4Sopenharmony_ci                    ref raw,
43867c3a3e4Sopenharmony_ci                },
43967c3a3e4Sopenharmony_ci                rest,
44067c3a3e4Sopenharmony_ci            )) => match literal::parse(raw) {
44167c3a3e4Sopenharmony_ci                Ok((_, result)) => Ok((rest, result)),
44267c3a3e4Sopenharmony_ci                _ => Err(Err::Error((input, crate::ErrorKind::InvalidLiteral).into())),
44367c3a3e4Sopenharmony_ci            },
44467c3a3e4Sopenharmony_ci            Some(_) => Err(Err::Error(
44567c3a3e4Sopenharmony_ci                (input, crate::ErrorKind::TypedToken(TokenKind::Literal)).into(),
44667c3a3e4Sopenharmony_ci            )),
44767c3a3e4Sopenharmony_ci        }
44867c3a3e4Sopenharmony_ci    }
44967c3a3e4Sopenharmony_ci
45067c3a3e4Sopenharmony_ci    fn string(self, input: &'_ [Token]) -> CResult<'_, Vec<u8>> {
45167c3a3e4Sopenharmony_ci        alt((
45267c3a3e4Sopenharmony_ci            map_opt(|i| self.literal(i), EvalResult::as_str),
45367c3a3e4Sopenharmony_ci            map_opt(|i| self.identifier(i), EvalResult::as_str),
45467c3a3e4Sopenharmony_ci        ))(input)
45567c3a3e4Sopenharmony_ci        .to_cexpr_result()
45667c3a3e4Sopenharmony_ci    }
45767c3a3e4Sopenharmony_ci
45867c3a3e4Sopenharmony_ci    // "string1" "string2" etc...
45967c3a3e4Sopenharmony_ci    fn concat_str(self, input: &'_ [Token]) -> CResult<'_, EvalResult> {
46067c3a3e4Sopenharmony_ci        map(
46167c3a3e4Sopenharmony_ci            pair(|i| self.string(i), many0(complete(|i| self.string(i)))),
46267c3a3e4Sopenharmony_ci            |(first, v)| {
46367c3a3e4Sopenharmony_ci                Vec::into_iter(v)
46467c3a3e4Sopenharmony_ci                    .fold(first, |mut s, elem| {
46567c3a3e4Sopenharmony_ci                        Vec::extend_from_slice(&mut s, Vec::<u8>::as_slice(&elem));
46667c3a3e4Sopenharmony_ci                        s
46767c3a3e4Sopenharmony_ci                    })
46867c3a3e4Sopenharmony_ci                    .into()
46967c3a3e4Sopenharmony_ci            },
47067c3a3e4Sopenharmony_ci        )(input)
47167c3a3e4Sopenharmony_ci        .to_cexpr_result()
47267c3a3e4Sopenharmony_ci    }
47367c3a3e4Sopenharmony_ci
47467c3a3e4Sopenharmony_ci    fn expr(self, input: &'_ [Token]) -> CResult<'_, EvalResult> {
47567c3a3e4Sopenharmony_ci        alt((
47667c3a3e4Sopenharmony_ci            |i| self.numeric_expr(i),
47767c3a3e4Sopenharmony_ci            delimited(p("("), |i| self.expr(i), p(")")),
47867c3a3e4Sopenharmony_ci            |i| self.concat_str(i),
47967c3a3e4Sopenharmony_ci            |i| self.literal(i),
48067c3a3e4Sopenharmony_ci            |i| self.identifier(i),
48167c3a3e4Sopenharmony_ci        ))(input)
48267c3a3e4Sopenharmony_ci        .to_cexpr_result()
48367c3a3e4Sopenharmony_ci    }
48467c3a3e4Sopenharmony_ci
48567c3a3e4Sopenharmony_ci    fn macro_definition(self, input: &'_ [Token]) -> CResult<'_, (&'_ [u8], EvalResult)> {
48667c3a3e4Sopenharmony_ci        pair(identifier_token, |i| self.expr(i))(input)
48767c3a3e4Sopenharmony_ci    }
48867c3a3e4Sopenharmony_ci}
48967c3a3e4Sopenharmony_ci
49067c3a3e4Sopenharmony_ciimpl<'a> ::std::ops::Deref for PRef<'a> {
49167c3a3e4Sopenharmony_ci    type Target = IdentifierParser<'a>;
49267c3a3e4Sopenharmony_ci    fn deref(&self) -> &IdentifierParser<'a> {
49367c3a3e4Sopenharmony_ci        self.0
49467c3a3e4Sopenharmony_ci    }
49567c3a3e4Sopenharmony_ci}
49667c3a3e4Sopenharmony_ci
49767c3a3e4Sopenharmony_ciimpl<'ident> IdentifierParser<'ident> {
49867c3a3e4Sopenharmony_ci    fn as_ref(&self) -> PRef<'_> {
49967c3a3e4Sopenharmony_ci        PRef(self)
50067c3a3e4Sopenharmony_ci    }
50167c3a3e4Sopenharmony_ci
50267c3a3e4Sopenharmony_ci    /// Create a new `IdentifierParser` with a set of known identifiers. When
50367c3a3e4Sopenharmony_ci    /// a known identifier is encountered during parsing, it is substituted
50467c3a3e4Sopenharmony_ci    /// for the value specified.
50567c3a3e4Sopenharmony_ci    pub fn new(identifiers: &HashMap<Vec<u8>, EvalResult>) -> IdentifierParser<'_> {
50667c3a3e4Sopenharmony_ci        IdentifierParser { identifiers }
50767c3a3e4Sopenharmony_ci    }
50867c3a3e4Sopenharmony_ci
50967c3a3e4Sopenharmony_ci    /// Parse and evaluate an expression of a list of tokens.
51067c3a3e4Sopenharmony_ci    ///
51167c3a3e4Sopenharmony_ci    /// Returns an error if the input is not a valid expression or if the token
51267c3a3e4Sopenharmony_ci    /// stream contains comments, keywords or unknown identifiers.
51367c3a3e4Sopenharmony_ci    pub fn expr<'a>(&self, input: &'a [Token]) -> CResult<'a, EvalResult> {
51467c3a3e4Sopenharmony_ci        self.as_ref().expr(input)
51567c3a3e4Sopenharmony_ci    }
51667c3a3e4Sopenharmony_ci
51767c3a3e4Sopenharmony_ci    /// Parse and evaluate a macro definition from a list of tokens.
51867c3a3e4Sopenharmony_ci    ///
51967c3a3e4Sopenharmony_ci    /// Returns the identifier for the macro and its replacement evaluated as an
52067c3a3e4Sopenharmony_ci    /// expression. The input should not include `#define`.
52167c3a3e4Sopenharmony_ci    ///
52267c3a3e4Sopenharmony_ci    /// Returns an error if the replacement is not a valid expression, if called
52367c3a3e4Sopenharmony_ci    /// on most function-like macros, or if the token stream contains comments,
52467c3a3e4Sopenharmony_ci    /// keywords or unknown identifiers.
52567c3a3e4Sopenharmony_ci    ///
52667c3a3e4Sopenharmony_ci    /// N.B. This is intended to fail on function-like macros, but if it the
52767c3a3e4Sopenharmony_ci    /// macro takes a single argument, the argument name is defined as an
52867c3a3e4Sopenharmony_ci    /// identifier, and the macro otherwise parses as an expression, it will
52967c3a3e4Sopenharmony_ci    /// return a result even on function-like macros.
53067c3a3e4Sopenharmony_ci    ///
53167c3a3e4Sopenharmony_ci    /// ```c
53267c3a3e4Sopenharmony_ci    /// // will evaluate into IDENTIFIER
53367c3a3e4Sopenharmony_ci    /// #define DELETE(IDENTIFIER)
53467c3a3e4Sopenharmony_ci    /// // will evaluate into IDENTIFIER-3
53567c3a3e4Sopenharmony_ci    /// #define NEGATIVE_THREE(IDENTIFIER)  -3
53667c3a3e4Sopenharmony_ci    /// ```
53767c3a3e4Sopenharmony_ci    pub fn macro_definition<'a>(&self, input: &'a [Token]) -> CResult<'a, (&'a [u8], EvalResult)> {
53867c3a3e4Sopenharmony_ci        crate::assert_full_parse(self.as_ref().macro_definition(input))
53967c3a3e4Sopenharmony_ci    }
54067c3a3e4Sopenharmony_ci}
54167c3a3e4Sopenharmony_ci
54267c3a3e4Sopenharmony_ci/// Parse and evaluate an expression of a list of tokens.
54367c3a3e4Sopenharmony_ci///
54467c3a3e4Sopenharmony_ci/// Returns an error if the input is not a valid expression or if the token
54567c3a3e4Sopenharmony_ci/// stream contains comments, keywords or identifiers.
54667c3a3e4Sopenharmony_cipub fn expr(input: &[Token]) -> CResult<'_, EvalResult> {
54767c3a3e4Sopenharmony_ci    IdentifierParser::new(&HashMap::new()).expr(input)
54867c3a3e4Sopenharmony_ci}
54967c3a3e4Sopenharmony_ci
55067c3a3e4Sopenharmony_ci/// Parse and evaluate a macro definition from a list of tokens.
55167c3a3e4Sopenharmony_ci///
55267c3a3e4Sopenharmony_ci/// Returns the identifier for the macro and its replacement evaluated as an
55367c3a3e4Sopenharmony_ci/// expression. The input should not include `#define`.
55467c3a3e4Sopenharmony_ci///
55567c3a3e4Sopenharmony_ci/// Returns an error if the replacement is not a valid expression, if called
55667c3a3e4Sopenharmony_ci/// on a function-like macro, or if the token stream contains comments,
55767c3a3e4Sopenharmony_ci/// keywords or identifiers.
55867c3a3e4Sopenharmony_cipub fn macro_definition(input: &[Token]) -> CResult<'_, (&'_ [u8], EvalResult)> {
55967c3a3e4Sopenharmony_ci    IdentifierParser::new(&HashMap::new()).macro_definition(input)
56067c3a3e4Sopenharmony_ci}
56167c3a3e4Sopenharmony_ci
56267c3a3e4Sopenharmony_ci/// Parse a functional macro declaration from a list of tokens.
56367c3a3e4Sopenharmony_ci///
56467c3a3e4Sopenharmony_ci/// Returns the identifier for the macro and the argument list (in order). The
56567c3a3e4Sopenharmony_ci/// input should not include `#define`. The actual definition is not parsed and
56667c3a3e4Sopenharmony_ci/// may be obtained from the unparsed data returned.
56767c3a3e4Sopenharmony_ci///
56867c3a3e4Sopenharmony_ci/// Returns an error if the input is not a functional macro or if the token
56967c3a3e4Sopenharmony_ci/// stream contains comments.
57067c3a3e4Sopenharmony_ci///
57167c3a3e4Sopenharmony_ci/// # Example
57267c3a3e4Sopenharmony_ci/// ```
57367c3a3e4Sopenharmony_ci/// use cexpr::expr::{IdentifierParser, EvalResult, fn_macro_declaration};
57467c3a3e4Sopenharmony_ci/// use cexpr::assert_full_parse;
57567c3a3e4Sopenharmony_ci/// use cexpr::token::Kind::*;
57667c3a3e4Sopenharmony_ci/// use cexpr::token::Token;
57767c3a3e4Sopenharmony_ci///
57867c3a3e4Sopenharmony_ci/// // #define SUFFIX(arg) arg "suffix"
57967c3a3e4Sopenharmony_ci/// let tokens = vec![
58067c3a3e4Sopenharmony_ci///     (Identifier,  &b"SUFFIX"[..]).into(),
58167c3a3e4Sopenharmony_ci///     (Punctuation, &b"("[..]).into(),
58267c3a3e4Sopenharmony_ci///     (Identifier,  &b"arg"[..]).into(),
58367c3a3e4Sopenharmony_ci///     (Punctuation, &b")"[..]).into(),
58467c3a3e4Sopenharmony_ci///     (Identifier,  &b"arg"[..]).into(),
58567c3a3e4Sopenharmony_ci///     (Literal,     &br#""suffix""#[..]).into(),
58667c3a3e4Sopenharmony_ci/// ];
58767c3a3e4Sopenharmony_ci///
58867c3a3e4Sopenharmony_ci/// // Try to parse the functional part
58967c3a3e4Sopenharmony_ci/// let (expr, (ident, args)) = fn_macro_declaration(&tokens).unwrap();
59067c3a3e4Sopenharmony_ci/// assert_eq!(ident, b"SUFFIX");
59167c3a3e4Sopenharmony_ci///
59267c3a3e4Sopenharmony_ci/// // Create dummy arguments
59367c3a3e4Sopenharmony_ci/// let idents = args.into_iter().map(|arg|
59467c3a3e4Sopenharmony_ci///     (arg.to_owned(), EvalResult::Str(b"test".to_vec()))
59567c3a3e4Sopenharmony_ci/// ).collect();
59667c3a3e4Sopenharmony_ci///
59767c3a3e4Sopenharmony_ci/// // Evaluate the macro
59867c3a3e4Sopenharmony_ci/// let (_, evaluated) = assert_full_parse(IdentifierParser::new(&idents).expr(expr)).unwrap();
59967c3a3e4Sopenharmony_ci/// assert_eq!(evaluated, EvalResult::Str(b"testsuffix".to_vec()));
60067c3a3e4Sopenharmony_ci/// ```
60167c3a3e4Sopenharmony_cipub fn fn_macro_declaration(input: &[Token]) -> CResult<'_, (&[u8], Vec<&[u8]>)> {
60267c3a3e4Sopenharmony_ci    pair(
60367c3a3e4Sopenharmony_ci        identifier_token,
60467c3a3e4Sopenharmony_ci        delimited(
60567c3a3e4Sopenharmony_ci            p("("),
60667c3a3e4Sopenharmony_ci            separated_list0(p(","), identifier_token),
60767c3a3e4Sopenharmony_ci            p(")"),
60867c3a3e4Sopenharmony_ci        ),
60967c3a3e4Sopenharmony_ci    )(input)
61067c3a3e4Sopenharmony_ci}
611