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::num::Wrapping;
24 use std::ops::{
25     AddAssign, BitAndAssign, BitOrAssign, BitXorAssign, DivAssign, MulAssign, RemAssign, ShlAssign,
26     ShrAssign, SubAssign,
27 };
28 
29 use crate::literal::{self, CChar};
30 use crate::token::{Kind as TokenKind, Token};
31 use crate::ToCexprResult;
32 use nom::branch::alt;
33 use nom::combinator::{complete, map, map_opt};
34 use nom::multi::{fold_many0, many0, separated_list};
35 use nom::sequence::{delimited, pair, preceded};
36 use nom::*;
37 
38 /// Expression parser/evaluator that supports identifiers.
39 #[derive(Debug)]
40 pub struct IdentifierParser<'ident> {
41     identifiers: &'ident HashMap<Vec<u8>, EvalResult>,
42 }
43 #[derive(Copy, Clone)]
44 struct PRef<'a>(&'a IdentifierParser<'a>);
45 
46 /// A shorthand for the type of cexpr expression evaluation results.
47 pub type CResult<'a, R> = IResult<&'a [Token], R, crate::Error<&'a [Token]>>;
48 
49 /// The result of parsing a literal or evaluating an expression.
50 #[derive(Debug, Clone, PartialEq)]
51 #[allow(missing_docs)]
52 pub enum EvalResult {
53     Int(Wrapping<i64>),
54     Float(f64),
55     Char(CChar),
56     Str(Vec<u8>),
57     Invalid,
58 }
59 
60 macro_rules! result_opt (
61 	(fn $n:ident: $e:ident -> $t:ty) => (
62 		#[allow(dead_code)]
63         #[allow(clippy::wrong_self_convention)]
64 		fn $n(self) -> Option<$t> {
65 			if let EvalResult::$e(v) = self {
66 				Some(v)
67 			} else {
68 				None
69 			}
70 		}
71 	);
72 );
73 
74 impl EvalResult {
75     result_opt!(fn as_int: Int -> Wrapping<i64>);
76     result_opt!(fn as_float: Float -> f64);
77     result_opt!(fn as_char: Char -> CChar);
78     result_opt!(fn as_str: Str -> Vec<u8>);
79 
80     #[allow(clippy::wrong_self_convention)]
as_numeric(self) -> Option<EvalResult>81     fn as_numeric(self) -> Option<EvalResult> {
82         match self {
83             EvalResult::Int(_) | EvalResult::Float(_) => Some(self),
84             _ => None,
85         }
86     }
87 }
88 
89 impl From<Vec<u8>> for EvalResult {
from(s: Vec<u8>) -> EvalResult90     fn from(s: Vec<u8>) -> EvalResult {
91         EvalResult::Str(s)
92     }
93 }
94 
95 // ===========================================
96 // ============= Clang tokens ================
97 // ===========================================
98 
99 macro_rules! exact_token (
100 	($k:ident, $c:expr) => ({
101         move |input: &[Token]| {
102 		if input.is_empty() {
103 			let res: CResult<'_, &[u8]> = Err(crate::nom::Err::Incomplete(Needed::Size($c.len())));
104 			res
105 		} else {
106 			if input[0].kind==TokenKind::$k && &input[0].raw[..]==$c {
107 				Ok((&input[1..], &input[0].raw[..]))
108 			} else {
109 				Err(crate::nom::Err::Error((input, crate::ErrorKind::ExactToken(TokenKind::$k,$c)).into()))
110 			}
111 		}
112         }
113 	});
114 );
115 
116 macro_rules! typed_token (
117 	($k:ident) => ({
118         move |input: &[Token]| {
119 		if input.is_empty() {
120 			let res: CResult<'_, &[u8]> = Err(nom::Err::Incomplete(Needed::Size(1)));
121 			res
122 		} else {
123 			if input[0].kind==TokenKind::$k {
124 				Ok((&input[1..], &input[0].raw[..]))
125 			} else {
126 				Err(crate::nom::Err::Error((input, crate::ErrorKind::TypedToken(TokenKind::$k)).into()))
127 			}
128 		}
129         }
130 	});
131 );
132 
133 #[allow(dead_code)]
any_token(input: &[Token]) -> CResult<'_, &Token>134 fn any_token(input: &[Token]) -> CResult<'_, &Token> {
135     if input.is_empty() {
136         Err(crate::nom::Err::Incomplete(Needed::Size(1)))
137     } else {
138         Ok((&input[1..], &input[0]))
139     }
140 }
141 
p(c: &'static str) -> impl Fn(&[Token]) -> CResult<'_, &[u8]>142 fn p(c: &'static str) -> impl Fn(&[Token]) -> CResult<'_, &[u8]> {
143     exact_token!(Punctuation, c.as_bytes())
144 }
145 
one_of_punctuation(c: &'static [&'static str]) -> impl Fn(&[Token]) -> CResult<'_, &[u8]>146 fn one_of_punctuation(c: &'static [&'static str]) -> impl Fn(&[Token]) -> CResult<'_, &[u8]> {
147     move |input| {
148         if input.is_empty() {
149             let min = c
150                 .iter()
151                 .map(|opt| opt.len())
152                 .min()
153                 .expect("at least one option");
154             Err(crate::nom::Err::Incomplete(Needed::Size(min)))
155         } else if input[0].kind == TokenKind::Punctuation
156             && c.iter().any(|opt| opt.as_bytes() == &input[0].raw[..])
157         {
158             Ok((&input[1..], &input[0].raw[..]))
159         } else {
160             Err(crate::nom::Err::Error(
161                 (
162                     input,
163                     crate::ErrorKind::ExactTokens(TokenKind::Punctuation, c),
164                 )
165                     .into(),
166             ))
167         }
168     }
169 }
170 
171 // ==================================================
172 // ============= Numeric expressions ================
173 // ==================================================
174 
175 impl<'a> AddAssign<&'a EvalResult> for EvalResult {
add_assign(&mut self, rhs: &'a EvalResult)176     fn add_assign(&mut self, rhs: &'a EvalResult) {
177         use self::EvalResult::*;
178         *self = match (&*self, rhs) {
179             (&Int(a), &Int(b)) => Int(a + b),
180             (&Float(a), &Int(b)) => Float(a + (b.0 as f64)),
181             (&Int(a), &Float(b)) => Float(a.0 as f64 + b),
182             (&Float(a), &Float(b)) => Float(a + b),
183             _ => Invalid,
184         };
185     }
186 }
187 impl<'a> BitAndAssign<&'a EvalResult> for EvalResult {
bitand_assign(&mut self, rhs: &'a EvalResult)188     fn bitand_assign(&mut self, rhs: &'a EvalResult) {
189         use self::EvalResult::*;
190         *self = match (&*self, rhs) {
191             (&Int(a), &Int(b)) => Int(a & b),
192             _ => Invalid,
193         };
194     }
195 }
196 impl<'a> BitOrAssign<&'a EvalResult> for EvalResult {
bitor_assign(&mut self, rhs: &'a EvalResult)197     fn bitor_assign(&mut self, rhs: &'a EvalResult) {
198         use self::EvalResult::*;
199         *self = match (&*self, rhs) {
200             (&Int(a), &Int(b)) => Int(a | b),
201             _ => Invalid,
202         };
203     }
204 }
205 impl<'a> BitXorAssign<&'a EvalResult> for EvalResult {
bitxor_assign(&mut self, rhs: &'a EvalResult)206     fn bitxor_assign(&mut self, rhs: &'a EvalResult) {
207         use self::EvalResult::*;
208         *self = match (&*self, rhs) {
209             (&Int(a), &Int(b)) => Int(a ^ b),
210             _ => Invalid,
211         };
212     }
213 }
214 impl<'a> DivAssign<&'a EvalResult> for EvalResult {
div_assign(&mut self, rhs: &'a EvalResult)215     fn div_assign(&mut self, rhs: &'a EvalResult) {
216         use self::EvalResult::*;
217         *self = match (&*self, rhs) {
218             (&Int(a), &Int(b)) => Int(a / b),
219             (&Float(a), &Int(b)) => Float(a / (b.0 as f64)),
220             (&Int(a), &Float(b)) => Float(a.0 as f64 / b),
221             (&Float(a), &Float(b)) => Float(a / b),
222             _ => Invalid,
223         };
224     }
225 }
226 impl<'a> MulAssign<&'a EvalResult> for EvalResult {
mul_assign(&mut self, rhs: &'a EvalResult)227     fn mul_assign(&mut self, rhs: &'a EvalResult) {
228         use self::EvalResult::*;
229         *self = match (&*self, rhs) {
230             (&Int(a), &Int(b)) => Int(a * b),
231             (&Float(a), &Int(b)) => Float(a * (b.0 as f64)),
232             (&Int(a), &Float(b)) => Float(a.0 as f64 * b),
233             (&Float(a), &Float(b)) => Float(a * b),
234             _ => Invalid,
235         };
236     }
237 }
238 impl<'a> RemAssign<&'a EvalResult> for EvalResult {
rem_assign(&mut self, rhs: &'a EvalResult)239     fn rem_assign(&mut self, rhs: &'a EvalResult) {
240         use self::EvalResult::*;
241         *self = match (&*self, rhs) {
242             (&Int(a), &Int(b)) => Int(a % b),
243             (&Float(a), &Int(b)) => Float(a % (b.0 as f64)),
244             (&Int(a), &Float(b)) => Float(a.0 as f64 % b),
245             (&Float(a), &Float(b)) => Float(a % b),
246             _ => Invalid,
247         };
248     }
249 }
250 impl<'a> ShlAssign<&'a EvalResult> for EvalResult {
shl_assign(&mut self, rhs: &'a EvalResult)251     fn shl_assign(&mut self, rhs: &'a EvalResult) {
252         use self::EvalResult::*;
253         *self = match (&*self, rhs) {
254             (&Int(a), &Int(b)) => Int(a << (b.0 as usize)),
255             _ => Invalid,
256         };
257     }
258 }
259 impl<'a> ShrAssign<&'a EvalResult> for EvalResult {
shr_assign(&mut self, rhs: &'a EvalResult)260     fn shr_assign(&mut self, rhs: &'a EvalResult) {
261         use self::EvalResult::*;
262         *self = match (&*self, rhs) {
263             (&Int(a), &Int(b)) => Int(a >> (b.0 as usize)),
264             _ => Invalid,
265         };
266     }
267 }
268 impl<'a> SubAssign<&'a EvalResult> for EvalResult {
sub_assign(&mut self, rhs: &'a EvalResult)269     fn sub_assign(&mut self, rhs: &'a EvalResult) {
270         use self::EvalResult::*;
271         *self = match (&*self, rhs) {
272             (&Int(a), &Int(b)) => Int(a - b),
273             (&Float(a), &Int(b)) => Float(a - (b.0 as f64)),
274             (&Int(a), &Float(b)) => Float(a.0 as f64 - b),
275             (&Float(a), &Float(b)) => Float(a - b),
276             _ => Invalid,
277         };
278     }
279 }
280 
unary_op(input: (&[u8], EvalResult)) -> Option<EvalResult>281 fn unary_op(input: (&[u8], EvalResult)) -> Option<EvalResult> {
282     use self::EvalResult::*;
283     assert_eq!(input.0.len(), 1);
284     match (input.0[0], input.1) {
285         (b'+', i) => Some(i),
286         (b'-', Int(i)) => Some(Int(Wrapping(i.0.wrapping_neg()))), // impl Neg for Wrapping not until rust 1.10...
287         (b'-', Float(i)) => Some(Float(-i)),
288         (b'-', _) => unreachable!("non-numeric unary op"),
289         (b'~', Int(i)) => Some(Int(!i)),
290         (b'~', Float(_)) => None,
291         (b'~', _) => unreachable!("non-numeric unary op"),
292         _ => unreachable!("invalid unary op"),
293     }
294 }
295 
numeric<I: Clone, E: nom::error::ParseError<I>, F>( f: F, ) -> impl Fn(I) -> nom::IResult<I, EvalResult, E> where F: Fn(I) -> nom::IResult<I, EvalResult, E>,296 fn numeric<I: Clone, E: nom::error::ParseError<I>, F>(
297     f: F,
298 ) -> impl Fn(I) -> nom::IResult<I, EvalResult, E>
299 where
300     F: Fn(I) -> nom::IResult<I, EvalResult, E>,
301 {
302     nom::combinator::map_opt(f, EvalResult::as_numeric)
303 }
304 
305 impl<'a> PRef<'a> {
unary(self, input: &'_ [Token]) -> CResult<'_, EvalResult>306     fn unary(self, input: &'_ [Token]) -> CResult<'_, EvalResult> {
307         alt((
308             delimited(p("("), |i| self.numeric_expr(i), p(")")),
309             numeric(|i| self.literal(i)),
310             numeric(|i| self.identifier(i)),
311             map_opt(
312                 pair(one_of_punctuation(&["+", "-", "~"][..]), |i| self.unary(i)),
313                 unary_op,
314             ),
315         ))(input)
316     }
317 
mul_div_rem(self, input: &'_ [Token]) -> CResult<'_, EvalResult>318     fn mul_div_rem(self, input: &'_ [Token]) -> CResult<'_, EvalResult> {
319         let (input, acc) = self.unary(input)?;
320         fold_many0(
321             pair(complete(one_of_punctuation(&["*", "/", "%"][..])), |i| {
322                 self.unary(i)
323             }),
324             acc,
325             |mut acc, (op, val): (&[u8], EvalResult)| {
326                 match op[0] as char {
327                     '*' => acc *= &val,
328                     '/' => acc /= &val,
329                     '%' => acc %= &val,
330                     _ => unreachable!(),
331                 };
332                 acc
333             },
334         )(input)
335     }
336 
add_sub(self, input: &'_ [Token]) -> CResult<'_, EvalResult>337     fn add_sub(self, input: &'_ [Token]) -> CResult<'_, EvalResult> {
338         let (input, acc) = self.mul_div_rem(input)?;
339         fold_many0(
340             pair(complete(one_of_punctuation(&["+", "-"][..])), |i| {
341                 self.mul_div_rem(i)
342             }),
343             acc,
344             |mut acc, (op, val): (&[u8], EvalResult)| {
345                 match op[0] as char {
346                     '+' => acc += &val,
347                     '-' => acc -= &val,
348                     _ => unreachable!(),
349                 };
350                 acc
351             },
352         )(input)
353     }
354 
shl_shr(self, input: &'_ [Token]) -> CResult<'_, EvalResult>355     fn shl_shr(self, input: &'_ [Token]) -> CResult<'_, EvalResult> {
356         let (input, acc) = self.add_sub(input)?;
357         numeric(fold_many0(
358             pair(complete(one_of_punctuation(&["<<", ">>"][..])), |i| {
359                 self.add_sub(i)
360             }),
361             acc,
362             |mut acc, (op, val): (&[u8], EvalResult)| {
363                 match op {
364                     b"<<" => acc <<= &val,
365                     b">>" => acc >>= &val,
366                     _ => unreachable!(),
367                 };
368                 acc
369             },
370         ))(input)
371     }
372 
and(self, input: &'_ [Token]) -> CResult<'_, EvalResult>373     fn and(self, input: &'_ [Token]) -> CResult<'_, EvalResult> {
374         let (input, acc) = self.shl_shr(input)?;
375         numeric(fold_many0(
376             preceded(complete(p("&")), |i| self.shl_shr(i)),
377             acc,
378             |mut acc, val: EvalResult| {
379                 acc &= &val;
380                 acc
381             },
382         ))(input)
383     }
384 
xor(self, input: &'_ [Token]) -> CResult<'_, EvalResult>385     fn xor(self, input: &'_ [Token]) -> CResult<'_, EvalResult> {
386         let (input, acc) = self.and(input)?;
387         numeric(fold_many0(
388             preceded(complete(p("^")), |i| self.and(i)),
389             acc,
390             |mut acc, val: EvalResult| {
391                 acc ^= &val;
392                 acc
393             },
394         ))(input)
395     }
396 
or(self, input: &'_ [Token]) -> CResult<'_, EvalResult>397     fn or(self, input: &'_ [Token]) -> CResult<'_, EvalResult> {
398         let (input, acc) = self.xor(input)?;
399         numeric(fold_many0(
400             preceded(complete(p("|")), |i| self.xor(i)),
401             acc,
402             |mut acc, val: EvalResult| {
403                 acc |= &val;
404                 acc
405             },
406         ))(input)
407     }
408 
409     #[inline(always)]
numeric_expr(self, input: &'_ [Token]) -> CResult<'_, EvalResult>410     fn numeric_expr(self, input: &'_ [Token]) -> CResult<'_, EvalResult> {
411         self.or(input)
412     }
413 }
414 
415 // =======================================================
416 // ============= Literals and identifiers ================
417 // =======================================================
418 
419 impl<'a> PRef<'a> {
identifier(self, input: &'_ [Token]) -> CResult<'_, EvalResult>420     fn identifier(self, input: &'_ [Token]) -> CResult<'_, EvalResult> {
421         match input.split_first() {
422             None => Err(Err::Incomplete(Needed::Size(1))),
423             Some((
424                 &Token {
425                     kind: TokenKind::Identifier,
426                     ref raw,
427                 },
428                 rest,
429             )) => {
430                 if let Some(r) = self.identifiers.get(&raw[..]) {
431                     Ok((rest, r.clone()))
432                 } else {
433                     Err(Err::Error(
434                         (input, crate::ErrorKind::UnknownIdentifier).into(),
435                     ))
436                 }
437             }
438             Some(_) => Err(Err::Error(
439                 (input, crate::ErrorKind::TypedToken(TokenKind::Identifier)).into(),
440             )),
441         }
442     }
443 
literal(self, input: &'_ [Token]) -> CResult<'_, EvalResult>444     fn literal(self, input: &'_ [Token]) -> CResult<'_, EvalResult> {
445         match input.split_first() {
446             None => Err(Err::Incomplete(Needed::Size(1))),
447             Some((
448                 &Token {
449                     kind: TokenKind::Literal,
450                     ref raw,
451                 },
452                 rest,
453             )) => match literal::parse(raw) {
454                 Ok((_, result)) => Ok((rest, result)),
455                 _ => Err(Err::Error((input, crate::ErrorKind::InvalidLiteral).into())),
456             },
457             Some(_) => Err(Err::Error(
458                 (input, crate::ErrorKind::TypedToken(TokenKind::Literal)).into(),
459             )),
460         }
461     }
462 
string(self, input: &'_ [Token]) -> CResult<'_, Vec<u8>>463     fn string(self, input: &'_ [Token]) -> CResult<'_, Vec<u8>> {
464         alt((
465             map_opt(|i| self.literal(i), EvalResult::as_str),
466             map_opt(|i| self.identifier(i), EvalResult::as_str),
467         ))(input)
468         .to_cexpr_result()
469     }
470 
471     // "string1" "string2" etc...
concat_str(self, input: &'_ [Token]) -> CResult<'_, EvalResult>472     fn concat_str(self, input: &'_ [Token]) -> CResult<'_, EvalResult> {
473         map(
474             pair(|i| self.string(i), many0(complete(|i| self.string(i)))),
475             |(first, v)| {
476                 Vec::into_iter(v)
477                     .fold(first, |mut s, elem| {
478                         Vec::extend_from_slice(&mut s, Vec::<u8>::as_slice(&elem));
479                         s
480                     })
481                     .into()
482             },
483         )(input)
484         .to_cexpr_result()
485     }
486 
expr(self, input: &'_ [Token]) -> CResult<'_, EvalResult>487     fn expr(self, input: &'_ [Token]) -> CResult<'_, EvalResult> {
488         alt((
489             |i| self.numeric_expr(i),
490             delimited(p("("), |i| self.expr(i), p(")")),
491             |i| self.concat_str(i),
492             |i| self.literal(i),
493             |i| self.identifier(i),
494         ))(input)
495         .to_cexpr_result()
496     }
497 
macro_definition(self, input: &'_ [Token]) -> CResult<'_, (&'_ [u8], EvalResult)>498     fn macro_definition(self, input: &'_ [Token]) -> CResult<'_, (&'_ [u8], EvalResult)> {
499         pair(typed_token!(Identifier), |i| self.expr(i))(input)
500     }
501 }
502 
503 impl<'a> ::std::ops::Deref for PRef<'a> {
504     type Target = IdentifierParser<'a>;
deref(&self) -> &IdentifierParser<'a>505     fn deref(&self) -> &IdentifierParser<'a> {
506         self.0
507     }
508 }
509 
510 impl<'ident> IdentifierParser<'ident> {
as_ref(&self) -> PRef<'_>511     fn as_ref(&self) -> PRef<'_> {
512         PRef(self)
513     }
514 
515     /// Create a new `IdentifierParser` with a set of known identifiers. When
516     /// a known identifier is encountered during parsing, it is substituted
517     /// for the value specified.
new(identifiers: &HashMap<Vec<u8>, EvalResult>) -> IdentifierParser<'_>518     pub fn new(identifiers: &HashMap<Vec<u8>, EvalResult>) -> IdentifierParser<'_> {
519         IdentifierParser { identifiers }
520     }
521 
522     /// Parse and evalute an expression of a list of tokens.
523     ///
524     /// Returns an error if the input is not a valid expression or if the token
525     /// stream contains comments, keywords or unknown identifiers.
expr<'a>(&self, input: &'a [Token]) -> CResult<'a, EvalResult>526     pub fn expr<'a>(&self, input: &'a [Token]) -> CResult<'a, EvalResult> {
527         self.as_ref().expr(input)
528     }
529 
530     /// Parse and evaluate a macro definition from of a list of tokens.
531     ///
532     /// Returns the identifier for the macro and its replacement evaluated as an
533     /// expression. The input should not include `#define`.
534     ///
535     /// Returns an error if the replacement is not a valid expression, if called
536     /// on most function-like macros, or if the token stream contains comments,
537     /// keywords or unknown identifiers.
538     ///
539     /// N.B. This is intended to fail on function-like macros, but if it the
540     /// macro takes a single argument, the argument name is defined as an
541     /// identifier, and the macro otherwise parses as an expression, it will
542     /// return a result even on function-like macros.
543     ///
544     /// ```c
545     /// // will evaluate into IDENTIFIER
546     /// #define DELETE(IDENTIFIER)
547     /// // will evaluate into IDENTIFIER-3
548     /// #define NEGATIVE_THREE(IDENTIFIER)  -3
549     /// ```
macro_definition<'a>(&self, input: &'a [Token]) -> CResult<'a, (&'a [u8], EvalResult)>550     pub fn macro_definition<'a>(&self, input: &'a [Token]) -> CResult<'a, (&'a [u8], EvalResult)> {
551         crate::assert_full_parse(self.as_ref().macro_definition(input))
552     }
553 }
554 
555 /// Parse and evalute an expression of a list of tokens.
556 ///
557 /// Returns an error if the input is not a valid expression or if the token
558 /// stream contains comments, keywords or identifiers.
expr(input: &[Token]) -> CResult<'_, EvalResult>559 pub fn expr(input: &[Token]) -> CResult<'_, EvalResult> {
560     IdentifierParser::new(&HashMap::new()).expr(input)
561 }
562 
563 /// Parse and evaluate a macro definition from of a list of tokens.
564 ///
565 /// Returns the identifier for the macro and its replacement evaluated as an
566 /// expression. The input should not include `#define`.
567 ///
568 /// Returns an error if the replacement is not a valid expression, if called
569 /// on a function-like macro, or if the token stream contains comments,
570 /// keywords or identifiers.
macro_definition(input: &[Token]) -> CResult<'_, (&'_ [u8], EvalResult)>571 pub fn macro_definition(input: &[Token]) -> CResult<'_, (&'_ [u8], EvalResult)> {
572     IdentifierParser::new(&HashMap::new()).macro_definition(input)
573 }
574 
575 /// Parse a functional macro declaration from a list of tokens.
576 ///
577 /// Returns the identifier for the macro and the argument list (in order). The
578 /// input should not include `#define`. The actual definition is not parsed and
579 /// may be obtained from the unparsed data returned.
580 ///
581 /// Returns an error if the input is not a functional macro or if the token
582 /// stream contains comments.
583 ///
584 /// # Example
585 /// ```
586 /// use cexpr::expr::{IdentifierParser, EvalResult, fn_macro_declaration};
587 /// use cexpr::assert_full_parse;
588 /// use cexpr::token::Kind::*;
589 /// use cexpr::token::Token;
590 ///
591 /// // #define SUFFIX(arg) arg "suffix"
592 /// let tokens = vec![
593 ///     (Identifier,  &b"SUFFIX"[..]).into(),
594 ///     (Punctuation, &b"("[..]).into(),
595 ///     (Identifier,  &b"arg"[..]).into(),
596 ///     (Punctuation, &b")"[..]).into(),
597 ///     (Identifier,  &b"arg"[..]).into(),
598 ///     (Literal,     &br#""suffix""#[..]).into(),
599 /// ];
600 ///
601 /// // Try to parse the functional part
602 /// let (expr, (ident, args)) = fn_macro_declaration(&tokens).unwrap();
603 /// assert_eq!(ident, b"SUFFIX");
604 ///
605 /// // Create dummy arguments
606 /// let idents = args.into_iter().map(|arg|
607 ///     (arg.to_owned(), EvalResult::Str(b"test".to_vec()))
608 /// ).collect();
609 ///
610 /// // Evaluate the macro
611 /// let (_, evaluated) = assert_full_parse(IdentifierParser::new(&idents).expr(expr)).unwrap();
612 /// assert_eq!(evaluated, EvalResult::Str(b"testsuffix".to_vec()));
613 /// ```
fn_macro_declaration(input: &[Token]) -> CResult<'_, (&[u8], Vec<&[u8]>)>614 pub fn fn_macro_declaration(input: &[Token]) -> CResult<'_, (&[u8], Vec<&[u8]>)> {
615     pair(
616         typed_token!(Identifier),
617         delimited(
618             p("("),
619             separated_list(p(","), typed_token!(Identifier)),
620             p(")"),
621         ),
622     )(input)
623 }
624