1 // (C) Copyright 2016 Jethro G. Beekman
2 //
3 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6 // option. This file may not be copied, modified, or distributed
7 // except according to those terms.
8 //! Evaluating C expressions from tokens.
9 //!
10 //! Numerical operators are supported. All numerical values are treated as
11 //! `i64` or `f64`. Type casting is not supported. `i64` are converted to
12 //! `f64` when used in conjunction with a `f64`. Right shifts are always
13 //! arithmetic shifts.
14 //!
15 //! The `sizeof` operator is not supported.
16 //!
17 //! String concatenation is supported, but width prefixes are ignored all
18 //! strings are treated as narrow strings.
19 //!
20 //! Use the `IdentifierParser` to substitute identifiers found in expressions.
21 
22 use std::collections::HashMap;
23 use std::ops::{AddAssign,BitAndAssign,BitOrAssign,BitXorAssign,DivAssign,MulAssign,RemAssign,ShlAssign,ShrAssign,SubAssign};
24 use std::num::Wrapping;
25 
26 use literal::{self,CChar};
27 use token::{Token,Kind as TokenKind};
28 use nom_crate::*;
29 
30 /// Expression parser/evaluator that supports identifiers.
31 #[derive(Debug)]
32 pub struct IdentifierParser<'ident> {
33 	identifiers: &'ident HashMap<Vec<u8>,EvalResult>,
34 }
35 #[derive(Copy,Clone)]
36 struct PRef<'a>(&'a IdentifierParser<'a>);
37 
38 pub type CResult<'a,R:'a> = IResult<&'a [Token],R,::Error>;
39 
40 /// The result of parsing a literal or evaluating an expression.
41 #[derive(Debug,Clone,PartialEq)]
42 pub enum EvalResult {
43 	Int(Wrapping<i64>),
44 	Float(f64),
45 	Char(CChar),
46 	Str(Vec<u8>),
47 	Invalid,
48 }
49 
50 macro_rules! result_opt (
51 	(fn $n:ident: $e:ident -> $t:ty) => (
52 		#[allow(dead_code)]
53 		fn $n(self) -> Option<$t> {
54 			if let EvalResult::$e(v) = self {
55 				Some(v)
56 			} else {
57 				None
58 			}
59 		}
60 	);
61 );
62 
63 impl EvalResult {
64 	result_opt!(fn as_int: Int -> Wrapping<i64>);
65 	result_opt!(fn as_float: Float -> f64);
66 	result_opt!(fn as_char: Char -> CChar);
67 	result_opt!(fn as_str: Str -> Vec<u8>);
68 
as_numeric(self) -> Option<EvalResult>69 	fn as_numeric(self) -> Option<EvalResult> {
70 		match self {
71 			EvalResult::Int(_) | EvalResult::Float(_) => Some(self),
72 			_ => None,
73 		}
74 	}
75 }
76 
77 impl From<Vec<u8>> for EvalResult {
from(s: Vec<u8>) -> EvalResult78 	fn from(s: Vec<u8>) -> EvalResult {
79 		EvalResult::Str(s)
80 	}
81 }
82 
83 // ===========================================
84 // ============= Clang tokens ================
85 // ===========================================
86 
87 macro_rules! exact_token (
88 	($i:expr, $k: ident, $c: expr) => ({
89 		if $i.is_empty() {
90 			let res: CResult<&[u8]> = IResult::Incomplete(Needed::Size(1));
91 			res
92 		} else {
93 			if $i[0].kind==TokenKind::$k && &$i[0].raw[..]==$c {
94 				IResult::Done(&$i[1..], &$i[0].raw[..])
95 			} else {
96 				IResult::Error(Err::Position(ErrorKind::Custom(::Error::ExactToken(TokenKind::$k,$c)), $i))
97 			}
98 		}
99 	});
100 );
101 
102 macro_rules! typed_token (
103 	($i:expr, $k: ident) => ({
104 		if $i.is_empty() {
105 			let res: CResult<&[u8]> = IResult::Incomplete(Needed::Size(1));
106 			res
107 		} else {
108 			if $i[0].kind==TokenKind::$k {
109 				IResult::Done(&$i[1..], &$i[0].raw[..])
110 			} else {
111 				IResult::Error(Err::Position(ErrorKind::Custom(::Error::TypedToken(TokenKind::$k)), $i))
112 			}
113 		}
114 	});
115 );
116 
117 macro_rules! any_token (
118 	($i:expr,) => ({
119 		if $i.is_empty() {
120 			let res: CResult<&Token> = IResult::Incomplete(Needed::Size(1));
121 			res
122 		} else {
123 			IResult::Done(&$i[1..], &$i[0])
124 		}
125 	});
126 );
127 
128 macro_rules! p (
129 	($i:expr, $c: expr) => (exact_token!($i,Punctuation,$c.as_bytes()))
130 );
131 
132 // ==================================================
133 // ============= Numeric expressions ================
134 // ==================================================
135 
136 impl<'a> AddAssign<&'a EvalResult> for EvalResult {
add_assign(&mut self, rhs: &'a EvalResult)137     fn add_assign(&mut self, rhs: &'a EvalResult) {
138 		use self::EvalResult::*;
139 		*self=match (&*self,rhs) {
140 			(&Int(a),  &Int(b))   => Int(a+b),
141 			(&Float(a),&Int(b))   => Float(a+(b.0 as f64)),
142 			(&Int(a),  &Float(b)) => Float(a.0 as f64+b),
143 			(&Float(a),&Float(b)) => Float(a+b),
144 			_ => Invalid
145 		};
146 	}
147 }
148 impl<'a> BitAndAssign<&'a EvalResult> for EvalResult {
bitand_assign(&mut self, rhs: &'a EvalResult)149     fn bitand_assign(&mut self, rhs: &'a EvalResult) {
150 		use self::EvalResult::*;
151 		*self=match (&*self,rhs) {
152 			(&Int(a),&Int(b)) => Int(a&b),
153 			_ => Invalid
154 		};	}
155 }
156 impl<'a> BitOrAssign<&'a EvalResult> for EvalResult {
bitor_assign(&mut self, rhs: &'a EvalResult)157     fn bitor_assign(&mut self, rhs: &'a EvalResult) {
158 		use self::EvalResult::*;
159 		*self=match (&*self,rhs) {
160 			(&Int(a),&Int(b)) => Int(a|b),
161 			_ => Invalid
162 		};
163 	}
164 }
165 impl<'a> BitXorAssign<&'a EvalResult> for EvalResult {
bitxor_assign(&mut self, rhs: &'a EvalResult)166     fn bitxor_assign(&mut self, rhs: &'a EvalResult) {
167 		use self::EvalResult::*;
168 		*self=match (&*self,rhs) {
169 			(&Int(a),&Int(b)) => Int(a^b),
170 			_ => Invalid
171 		};
172 	}
173 }
174 impl<'a> DivAssign<&'a EvalResult> for EvalResult {
div_assign(&mut self, rhs: &'a EvalResult)175     fn div_assign(&mut self, rhs: &'a EvalResult) {
176 		use self::EvalResult::*;
177 		*self=match (&*self,rhs) {
178 			(&Int(a),  &Int(b))   => Int(a/b),
179 			(&Float(a),&Int(b))   => Float(a/(b.0 as f64)),
180 			(&Int(a),  &Float(b)) => Float(a.0 as f64/b),
181 			(&Float(a),&Float(b)) => Float(a/b),
182 			_ => Invalid
183 		};
184 	}
185 }
186 impl<'a> MulAssign<&'a EvalResult> for EvalResult {
mul_assign(&mut self, rhs: &'a EvalResult)187     fn mul_assign(&mut self, rhs: &'a EvalResult) {
188 		use self::EvalResult::*;
189 		*self=match (&*self,rhs) {
190 			(&Int(a),  &Int(b))   => Int(a*b),
191 			(&Float(a),&Int(b))   => Float(a*(b.0 as f64)),
192 			(&Int(a),  &Float(b)) => Float(a.0 as f64*b),
193 			(&Float(a),&Float(b)) => Float(a*b),
194 			_ => Invalid
195 		};
196 	}
197 }
198 impl<'a> RemAssign<&'a EvalResult> for EvalResult {
rem_assign(&mut self, rhs: &'a EvalResult)199     fn rem_assign(&mut self, rhs: &'a EvalResult) {
200 		use self::EvalResult::*;
201 		*self=match (&*self,rhs) {
202 			(&Int(a),  &Int(b))   => Int(a%b),
203 			(&Float(a),&Int(b))   => Float(a%(b.0 as f64)),
204 			(&Int(a),  &Float(b)) => Float(a.0 as f64%b),
205 			(&Float(a),&Float(b)) => Float(a%b),
206 			_ => Invalid
207 		};
208 	}
209 }
210 impl<'a> ShlAssign<&'a EvalResult> for EvalResult {
shl_assign(&mut self, rhs: &'a EvalResult)211     fn shl_assign(&mut self, rhs: &'a EvalResult) {
212 		use self::EvalResult::*;
213 		*self=match (&*self,rhs) {
214 			(&Int(a),&Int(b)) => Int(a<<(b.0 as usize)),
215 			_ => Invalid
216 		};
217 	}
218 }
219 impl<'a> ShrAssign<&'a EvalResult> for EvalResult {
shr_assign(&mut self, rhs: &'a EvalResult)220     fn shr_assign(&mut self, rhs: &'a EvalResult) {
221 		use self::EvalResult::*;
222 		*self=match (&*self,rhs) {
223 			(&Int(a),&Int(b)) => Int(a>>(b.0 as usize)),
224 			_ => Invalid
225 		};
226 	}
227 }
228 impl<'a> SubAssign<&'a EvalResult> for EvalResult {
sub_assign(&mut self, rhs: &'a EvalResult)229     fn sub_assign(&mut self, rhs: &'a EvalResult) {
230 		use self::EvalResult::*;
231 		*self=match (&*self,rhs) {
232 			(&Int(a),  &Int(b))   => Int(a-b),
233 			(&Float(a),&Int(b))   => Float(a-(b.0 as f64)),
234 			(&Int(a),  &Float(b)) => Float(a.0 as f64-b),
235 			(&Float(a),&Float(b)) => Float(a-b),
236 			_ => Invalid
237 		};
238 	}
239 }
240 
unary_op(input: (&[u8],EvalResult)) -> Option<EvalResult>241 fn unary_op(input: (&[u8],EvalResult)) -> Option<EvalResult> {
242 	use self::EvalResult::*;
243 	assert_eq!(input.0.len(),1);
244 	match (input.0[0],input.1) {
245 		(b'+',i) => Some(i),
246 		(b'-',Int(i)) => Some(Int(Wrapping(i.0.wrapping_neg()))), // impl Neg for Wrapping not until rust 1.10...
247 		(b'-',Float(i)) => Some(Float(-i)),
248 		(b'-',_) => unreachable!("non-numeric unary op"),
249 		(b'~',Int(i)) => Some(Int(!i)),
250 		(b'~',Float(_)) => None,
251 		(b'~',_) => unreachable!("non-numeric unary op"),
252 		_ => unreachable!("invalid unary op"),
253 	}
254 }
255 
256 macro_rules! numeric (
257 	($i:expr, $submac:ident!( $($args:tt)* )) => (map_opt!($i,$submac!($($args)*),EvalResult::as_numeric));
258 	($i:expr, $f:expr ) => (map_opt!($i,call!($f),EvalResult::as_numeric));
259 );
260 
261 impl<'a> PRef<'a> {
262 	method!(unary<PRef<'a>,&[Token],EvalResult,::Error>, mut self,
263 		alt!(
264 			delimited!(p!("("),call_m!(self.numeric_expr),p!(")")) |
265 			numeric!(call_m!(self.literal)) |
266 			numeric!(call_m!(self.identifier)) |
267 			map_opt!(pair!(alt!( p!("+") | p!("-") | p!("~") ),call_m!(self.unary)),unary_op)
268 		)
269 	);
270 
271 	method!(mul_div_rem<PRef<'a>,&[Token],EvalResult,::Error>, mut self,
272 		chain!(
273 			mut acc: call_m!(self.unary) ~
274 			many0!(alt!(
275 				tap!(mul: preceded!(p!("*"), call_m!(self.unary)) => acc *= &mul) |
276 				tap!(div: preceded!(p!("/"), call_m!(self.unary)) => acc /= &div) |
277 				tap!(rem: preceded!(p!("%"), call_m!(self.unary)) => acc %= &rem)
278 			)),
279 			|| { return acc }
280 		)
281 	);
282 
283 	method!(add_sub<PRef<'a>,&[Token],EvalResult,::Error>, mut self,
284 		chain!(
285 			mut acc: call_m!(self.mul_div_rem) ~
286 			many0!(alt!(
287 				tap!(add: preceded!(p!("+"), call_m!(self.mul_div_rem)) => acc += &add) |
288 				tap!(sub: preceded!(p!("-"), call_m!(self.mul_div_rem)) => acc -= &sub)
289 			)),
290 			|| { return acc }
291 		)
292 	);
293 
294 	method!(shl_shr<PRef<'a>,&[Token],EvalResult,::Error>, mut self,
295 		numeric!(chain!(
296 			mut acc: call_m!(self.add_sub) ~
297 			many0!(alt!(
298 				tap!(shl: preceded!(p!("<<"), call_m!(self.add_sub)) => acc <<= &shl) |
299 				tap!(shr: preceded!(p!(">>"), call_m!(self.add_sub)) => acc >>= &shr)
300 			)),
301 			|| { return acc }
302 		))
303 	);
304 
305 	method!(and<PRef<'a>,&[Token],EvalResult,::Error>, mut self,
306 		numeric!(chain!(
307 			mut acc: call_m!(self.shl_shr) ~
308 			many0!(
309 				tap!(and: preceded!(p!("&"), call_m!(self.shl_shr)) => acc &= &and)
310 			),
311 			|| { return acc }
312 		))
313 	);
314 
315 	method!(xor<PRef<'a>,&[Token],EvalResult,::Error>, mut self,
316 		numeric!(chain!(
317 			mut acc: call_m!(self.and) ~
318 			many0!(
319 				tap!(xor: preceded!(p!("^"), call_m!(self.and)) => acc ^= &xor)
320 			),
321 			|| { return acc }
322 		))
323 	);
324 
325 	method!(or<PRef<'a>,&[Token],EvalResult,::Error>, mut self,
326 		numeric!(chain!(
327 			mut acc: call_m!(self.xor) ~
328 			many0!(
329 				tap!(or: preceded!(p!("|"), call_m!(self.xor)) => acc |= &or)
330 			),
331 			|| { return acc }
332 		))
333 	);
334 
335 	#[inline(always)]
numeric_expr(self, input: &[Token]) -> (Self,CResult<EvalResult>)336 	fn numeric_expr(self, input: &[Token]) -> (Self,CResult<EvalResult>) {
337 		self.or(input)
338 	}
339 }
340 
341 // =======================================================
342 // ============= Literals and identifiers ================
343 // =======================================================
344 
345 impl<'a> PRef<'a> {
identifier(self, input: &[Token]) -> (Self,CResult<EvalResult>)346 	fn identifier(self, input: &[Token]) -> (Self,CResult<EvalResult>) {
347 		(self,match input.split_first() {
348 			None =>
349 				IResult::Incomplete(Needed::Size(1)),
350 			Some((&Token{kind:TokenKind::Identifier,ref raw},rest)) => {
351 				if let Some(r) = self.identifiers.get(&raw[..]) {
352 					IResult::Done(rest, r.clone())
353 				} else {
354 					IResult::Error(Err::Position(ErrorKind::Custom(::Error::UnknownIdentifier), input))
355 				}
356 			},
357 			Some(_) =>
358 				IResult::Error(Err::Position(ErrorKind::Custom(::Error::TypedToken(TokenKind::Identifier)), input)),
359 		})
360 	}
361 
literal(self, input: &[Token]) -> (Self,CResult<EvalResult>)362 	fn literal(self, input: &[Token]) -> (Self,CResult<EvalResult>) {
363 		(self,match input.split_first() {
364 			None =>
365 				IResult::Incomplete(Needed::Size(1)),
366 			Some((&Token{kind:TokenKind::Literal,ref raw},rest)) =>
367 				match literal::parse(raw) {
368 					IResult::Done(_,result) => IResult::Done(rest, result),
369 					_ => IResult::Error(Err::Position(ErrorKind::Custom(::Error::InvalidLiteral), input))
370 				},
371 			Some(_) =>
372 				IResult::Error(Err::Position(ErrorKind::Custom(::Error::TypedToken(TokenKind::Literal)), input)),
373 		})
374 	}
375 
376 	method!(string<PRef<'a>,&[Token],Vec<u8>,::Error>, mut self,
377 		alt!(
378 			map_opt!(call_m!(self.literal),EvalResult::as_str) |
379 			map_opt!(call_m!(self.identifier),EvalResult::as_str)
380 		)
381 	);
382 
383 	// "string1" "string2" etc...
384 	method!(concat_str<PRef<'a>,&[Token],EvalResult,::Error>, mut self,
385 		map!(
386 			pair!(call_m!(self.string),many0!(call_m!(self.string))),
387 			|(first,v)| Vec::into_iter(v).fold(first,|mut s,elem|{Vec::extend_from_slice(&mut s,Vec::<u8>::as_slice(&elem));s}).into()
388 		)
389 	);
390 
391 	method!(expr<PRef<'a>,&[Token],EvalResult,::Error>, mut self,
392 		alt!(
393 			delimited!(p!("("),call_m!(self.expr),p!(")")) |
394 			call_m!(self.numeric_expr) |
395 			call_m!(self.concat_str) |
396 			call_m!(self.literal) |
397 			call_m!(self.identifier)
398 		)
399 	);
400 
401 	method!(macro_definition<PRef<'a>,&[Token],(&[u8],EvalResult),::Error>, mut self,
402 		pair!(typed_token!(Identifier),call_m!(self.expr))
403 	);
404 }
405 
406 impl<'a> ::std::ops::Deref for PRef<'a> {
407 	type Target=IdentifierParser<'a>;
deref(&self) -> &IdentifierParser<'a>408 	fn deref(&self) -> &IdentifierParser<'a> {
409 		self.0
410 	}
411 }
412 
413 impl<'ident> IdentifierParser<'ident> {
as_ref(&self) -> PRef414 	fn as_ref(&self) -> PRef {
415 		PRef(self)
416 	}
417 
418 	/// Create a new `IdentifierParser` with a set of known identifiers. When
419 	/// a known identifier is encountered during parsing, it is substituted
420 	/// for the value specified.
new(identifiers: &HashMap<Vec<u8>,EvalResult>) -> IdentifierParser421 	pub fn new(identifiers: &HashMap<Vec<u8>,EvalResult>) -> IdentifierParser {
422 		IdentifierParser{identifiers:identifiers}
423 	}
424 
425 	/// Parse and evalute an expression of a list of tokens.
426 	///
427 	/// Returns an error if the input is not a valid expression or if the token
428 	/// stream contains comments, keywords or unknown identifiers.
expr<'a>(&self,input: &'a [Token]) -> CResult<'a,EvalResult>429 	pub fn expr<'a>(&self,input: &'a [Token]) -> CResult<'a,EvalResult> {
430 		self.as_ref().expr(input).1
431 	}
432 
433 	/// Parse and evaluate a macro definition from of a list of tokens.
434 	///
435 	/// Returns the identifier for the macro and its replacement evaluated as an
436 	/// expression. The input should not include `#define`.
437 	///
438 	/// Returns an error if the replacement is not a valid expression, if called
439 	/// on most function-like macros, or if the token stream contains comments,
440 	/// keywords or unknown identifiers.
441 	///
442 	/// N.B. This is intended to fail on function-like macros, but if it the
443 	/// macro takes a single argument, the argument name is defined as an
444 	/// identifier, and the macro otherwise parses as an expression, it will
445 	/// return a result even on function-like macros.
446 	///
447 	/// ```ignore
448 	/// // will evaluate into IDENTIFIER
449 	/// #define DELETE(IDENTIFIER)
450 	/// // will evaluate into IDENTIFIER-3
451 	/// #define NEGATIVE_THREE(IDENTIFIER)  -3
452 	/// ```
macro_definition<'a>(&self,input: &'a [Token]) -> CResult<'a,(&'a [u8],EvalResult)>453 	pub fn macro_definition<'a>(&self,input: &'a [Token]) -> CResult<'a,(&'a [u8],EvalResult)> {
454 		::assert_full_parse(self.as_ref().macro_definition(input).1)
455 	}
456 }
457 
458 /// Parse and evalute an expression of a list of tokens.
459 ///
460 /// Returns an error if the input is not a valid expression or if the token
461 /// stream contains comments, keywords or identifiers.
expr<'a>(input: &'a [Token]) -> CResult<'a,EvalResult>462 pub fn expr<'a>(input: &'a [Token]) -> CResult<'a,EvalResult> {
463 	IdentifierParser::new(&HashMap::new()).expr(input)
464 }
465 
466 /// Parse and evaluate a macro definition from of a list of tokens.
467 ///
468 /// Returns the identifier for the macro and its replacement evaluated as an
469 /// expression. The input should not include `#define`.
470 ///
471 /// Returns an error if the replacement is not a valid expression, if called
472 /// on a function-like macro, or if the token stream contains comments,
473 /// keywords or identifiers.
macro_definition<'a>(input: &'a [Token]) -> CResult<'a,(&'a [u8],EvalResult)>474 pub fn macro_definition<'a>(input: &'a [Token]) -> CResult<'a,(&'a [u8],EvalResult)> {
475 	IdentifierParser::new(&HashMap::new()).macro_definition(input)
476 }
477