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  //! A C expression parser and evaluator.
9  //!
10  //! This crate provides methods for parsing and evaluating simple C expressions. In general, the
11  //! crate can handle most arithmetic expressions that would appear in macros or the definition of
12  //! constants, as well as string and character constants.
13  //!
14  //! The main entry point for is [`token::parse`], which parses a byte string and returns its
15  //! evaluated value.
16  #![warn(rust_2018_idioms)]
17  #![warn(missing_docs)]
18  #![allow(deprecated)]
19  
20  pub mod nom {
21      //! nom's result types, re-exported.
22      pub use nom::{error::ErrorKind, error::Error, Err, IResult, Needed};
23  }
24  pub mod expr;
25  pub mod literal;
26  pub mod token;
27  
28  /// Parsing errors specific to C parsing
29  #[derive(Debug)]
30  pub enum ErrorKind {
31      /// Expected the specified token
32      ExactToken(token::Kind, &'static [u8]),
33      /// Expected one of the specified tokens
34      ExactTokens(token::Kind, &'static [&'static str]),
35      /// Expected a token of the specified kind
36      TypedToken(token::Kind),
37      /// An unknown identifier was encountered
38      UnknownIdentifier,
39      /// An invalid literal was encountered.
40      ///
41      /// When encountered, this generally means a bug exists in the data that
42      /// was passed in or the parsing logic.
43      InvalidLiteral,
44      /// A full parse was requested, but data was left over after parsing finished.
45      Partial,
46      /// An error occurred in an underlying nom parser.
47      Parser(nom::ErrorKind),
48  }
49  
50  impl From<nom::ErrorKind> for ErrorKind {
from(k: nom::ErrorKind) -> Self51      fn from(k: nom::ErrorKind) -> Self {
52          ErrorKind::Parser(k)
53      }
54  }
55  
56  impl From<u32> for ErrorKind {
from(_: u32) -> Self57      fn from(_: u32) -> Self {
58          ErrorKind::InvalidLiteral
59      }
60  }
61  
62  /// Parsing errors specific to C parsing.
63  ///
64  /// This is a superset of `(I, nom::ErrorKind)` that includes the additional errors specified by
65  /// [`ErrorKind`].
66  #[derive(Debug)]
67  pub struct Error<I> {
68      /// The remainder of the input stream at the time of the error.
69      pub input: I,
70      /// The error that occurred.
71      pub error: ErrorKind,
72  }
73  
74  impl<I> From<(I, nom::ErrorKind)> for Error<I> {
from(e: (I, nom::ErrorKind)) -> Self75      fn from(e: (I, nom::ErrorKind)) -> Self {
76          Self::from((e.0, ErrorKind::from(e.1)))
77      }
78  }
79  
80  impl<I> From<(I, ErrorKind)> for Error<I> {
from(e: (I, ErrorKind)) -> Self81      fn from(e: (I, ErrorKind)) -> Self {
82          Self {
83              input: e.0,
84              error: e.1,
85          }
86      }
87  }
88  
89  impl<I> From<::nom::error::Error<I>> for Error<I> {
from(e: ::nom::error::Error<I>) -> Self90      fn from(e: ::nom::error::Error<I>) -> Self {
91          Self {
92              input: e.input,
93              error: e.code.into(),
94          }
95      }
96  }
97  
98  impl<I> ::nom::error::ParseError<I> for Error<I> {
from_error_kind(input: I, kind: nom::ErrorKind) -> Self99      fn from_error_kind(input: I, kind: nom::ErrorKind) -> Self {
100          Self {
101              input,
102              error: kind.into(),
103          }
104      }
105  
append(_: I, _: nom::ErrorKind, other: Self) -> Self106      fn append(_: I, _: nom::ErrorKind, other: Self) -> Self {
107          other
108      }
109  }
110  
111  // in lieu of https://github.com/Geal/nom/issues/1010
112  trait ToCexprResult<I, O> {
to_cexpr_result(self) -> nom::IResult<I, O, Error<I>>113      fn to_cexpr_result(self) -> nom::IResult<I, O, Error<I>>;
114  }
115  impl<I, O, E> ToCexprResult<I, O> for nom::IResult<I, O, E>
116  where
117      Error<I>: From<E>,
118  {
to_cexpr_result(self) -> nom::IResult<I, O, Error<I>>119      fn to_cexpr_result(self) -> nom::IResult<I, O, Error<I>> {
120          match self {
121              Ok(v) => Ok(v),
122              Err(nom::Err::Incomplete(n)) => Err(nom::Err::Incomplete(n)),
123              Err(nom::Err::Error(e)) => Err(nom::Err::Error(e.into())),
124              Err(nom::Err::Failure(e)) => Err(nom::Err::Failure(e.into())),
125          }
126      }
127  }
128  
129  /// If the input result indicates a succesful parse, but there is data left,
130  /// return an `Error::Partial` instead.
assert_full_parse<'i, I: 'i, O, E>( result: nom::IResult<&'i [I], O, E>, ) -> nom::IResult<&'i [I], O, Error<&'i [I]>> where Error<&'i [I]>: From<E>,131  pub fn assert_full_parse<'i, I: 'i, O, E>(
132      result: nom::IResult<&'i [I], O, E>,
133  ) -> nom::IResult<&'i [I], O, Error<&'i [I]>>
134  where
135      Error<&'i [I]>: From<E>,
136  {
137      match result.to_cexpr_result() {
138          Ok((rem, output)) => {
139              if rem.is_empty() {
140                  Ok((rem, output))
141              } else {
142                  Err(nom::Err::Error((rem, ErrorKind::Partial).into()))
143              }
144          }
145          Err(nom::Err::Incomplete(n)) => Err(nom::Err::Incomplete(n)),
146          Err(nom::Err::Failure(e)) => Err(nom::Err::Failure(e)),
147          Err(nom::Err::Error(e)) => Err(nom::Err::Error(e)),
148      }
149  }
150