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