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